关于多线程和线程安全相关讨论(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bloodylzy/article/details/79139466

对于一般的业务逻辑处理而言,单线程已经满足了业务要求。普通来说,new一个对象,调用其中的方法,方法结束以后,对象不再被引用,然后被GC。这基本就已经能够应对日常的开发需求了。

一:线程

首先我们来明确一个东西,进程,线程,协程这三个东西。官方一点的解释就是:

1.每一个进程都有独立的代码和内存空间,一个进程包含1~n个线程,进程是资源分配的最小单位

2.同一类线程共享代码和数据空间,每隔线程有独立的运行栈和程序计数器,线程是CPU的最小调度单位

3.协程属于更轻量级的线程,类比进程和线程之间的关系

然后我们再来看看JVMJVM将内存数据分为程序计数器Java本地方法栈Java方法区。这些大家都了解,我们就不多做介绍了。

结合两者,我们可以得到一个图


了解了这个以后,大家基本就能理解了为什么会发生线程安全的问题了。

接下来我们继续来讲线程的五个状态

1.新建状态:新创建了一个线程

2.就绪状态:线程处于可运行的线程池中,然后等待CPU的使用权

3.运行状态:成功拿到CPU的使用权,开始执行代码

4.阻塞状态:线程因为某些原因放弃了CPU的使用权,暂停运行,直到线程重新回到就绪状态,然后等待再次获得CPU的使用权

死亡状态:线程的run方法结束或者是发生异常退出了,这时候线程结束了生命周期

套用网上的图


关于线程的实现方式,主要是分为三种,分别是实现Runnable接口继承Thread方法实现Callable接口Callable接口主要是牵扯到Future模式,相关的实现大家可以到下面仔细看。

一般来说,实现Runnable接口和继承Thread方法是我们最常用的两种方式。其实Thread也是实现了Runnable接口,所以我们实质上都是重写run方法。run方法的实现,是多线程实现的基础,所有的多线程代码都是在run方法里面。但是基本上所有的多线程的运行,都是依赖于Threadstart方法

虽然说多线程的实现方式有两种,但是还是建议大家使用前者,也就是去实现Runnable接口,主要原因就是一个类如果继承了Thread,则不适合资源的共享,但是如果实现了Runnable接口,就很容易实现资源的共享。以下是总结出来的实现Runnable接口比继承Thread类的优势:

1.适合多个相同的程序代码的线程去处理一个资源

2.可以避免Java中单继承的限制

3.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

4.线程池只能放入实现了Runnable接口或者实现了Callable接口的类,无法放入继承Thread类的类

关于第四条,这里说明一下,关于继承Thread的类,线程池可以execute,但是无法submit

 

我们对于线程类常用的方法,无非也就是sleep(),wait(),interrupt(),currentThread(),setName(),setPriority(),yield(),notify(),join()这几个方法而已。下面给大家解释一下这些方法:

Sleep():让当前正在执行的线程休眠,传参为休眠时间(毫秒数),注意sleep方法是不释放锁的

Wait():让当前正在执行的线程等待,注意,wait方法是释放锁的

Interrupt():对于这个方法,我个人的解释倾向于检查线程运行状态。注意,这个方法不是中断线程。当你调用这个方法的时候,如果线程正在正常的执行,那么这个线程是不会抛出错误的,只有当这个线程处于wait/sleep/join的时候,才会抛出错误,但是,如果你catch了这个错误,那么这个线程就不会因为这个异常而停止。

currentThread():这个方法是得到当前线程。

setName():设置线程的名称

setPriority():设置线程的优先级;这里提一下Java线程的优先级,Java线程的优先级分成1~10,默认是5,优先级越高的,线程也就优先执行。

Yield():使得线程从运行状态返回到可执行状态。


猜你喜欢

转载自blog.csdn.net/bloodylzy/article/details/79139466