Java线程生命周期及状态、Java线程安全的的理解、Thread与Runnable、Java守护线程

线程生命周期

线程可分为五种状态,创建、就绪、运行、阻塞、死亡这五个状态。

创建状态
这个没有什么需要描述的,就是创建(new )一个新的线程对象

就绪状态
线程对象创建后、调用对象的start()方法,该线程将会处于可运行线程池中,变为可运行后等待获取CPU的使用权

运行状态
就是这就绪状态下的线程获取到了CPU使用权,然后开始执行编写的代码

阻塞状态
1、等待阻塞:运行的线程调用wait方法,使用wait方法后前线会释放占用的所有资源,jvm会将线程放入“待池种”中。进入这个状态后,线程是无法自己再次运行的,需要其他线程调用notify()或者notifyAll()方法才能唤醒线程,wait方法是object中的方法
2、同步阻塞:运行的线程这获取同步锁时,当前锁已经被其他线程获取到了,则jvm会将当前线程放入“锁池”中。等待当前占用锁资源的线程释放锁以后,在进行锁的获取
3、其他阻塞:比如说运行线程调用sleep()或者join()方法,线程会进入阻塞,知道sleep()时间结束,join等待线程执行完毕,线程重新转入就绪状态

死亡状态
线程执行完毕、或者因为异常退出了run方法,该线程的生命周期就结束了

sleep、wait、join、yield方法简介

sleep方法
sleep()是Thread类中的静态方法,可以理解为把当前的CPU执行资格让出去,不再执行当前线程的内容,当设置的休眠时间结束,再去获取CPU资源获取到后在继续运行。如果使用sleep方法时有锁,那么sleep是不会释放锁的,会把这个锁带入冻结状态,也就是其他线程不可能获取到这个锁

wait方法
wait()是Object的方法,当我们调用wait方法后,线程会释放所有的资源,如果线程获取到了锁,锁也是会被释放的,然后线程会进入到“等待池”中。只有调用notify()或者notifyAll()方法才能唤醒线程,要注意的是notify只是随机唤醒“等待池”中某一个等待的线程,notifyAll是唤醒全部等待的线程

join方法
join执行后线程进入阻塞状态,但这个调用是需要另外一个线程调用的,例如为这mian()方法中创建一个新的线程,此时在mian方法中调用这个新线程的join方法,就可以让为的mian方法进入阻塞状态,直到为那个新线程执行完毕或者中断。为更容易让人理解,下面为示例代码与运行结果图片如下
Java线程生命周期及状态、Java线程安全的的理解、Thread与Runnable、Java守护线程_第1张图片
yield方法
yield()方法执行后,线程马上进入就绪状态,释放CPU资源,但是依然保留获取CPU的执行资格,有可能你现在释放然后马上又再次获取到CPU执行资格,然后继续执行当前线程中的内容

线程安全的理解

简介
实际上来说,不应该叫做线程安全,应该是内存安全,堆内存是共享的可以被所有线程访问

判断一个线程是否安全
例如多个线程访问一个对象,因为对象是保存这堆中的,这就是我前面说的,线程安全实际上是内存安全。如果不需要额外的同步或者协调控制操作,调用这个对象时都可以获取到正确的结果,我们就可以将当前线程定义为安全线程。

正确的结果
正确的结果怎么来定义比如说,我们在单线程下的执行和在多个线程下的执行,结果是永远可以保持一致的,这个就可以被定义为正确的结果。反之如果单线程执行与多线程执行出现结果不一致的情况,则当前线程为不安全的,此类线程需要进行额外的同步或者协调操作,这样才能保证正确的结果

Thread与Runnable

Thread实际上就是实现了Runnable接口,然后进行了更多的扩展,两者的关系是继承关系。使用上来说,都需要new Thread,然后执行Run方法。Thread与Runnable两个的用法来说,个人感觉如果是复杂的线程操作需求,那就选择继承Thread,如果只是简单的执行多线程任务,那就实现Runnable。不过还有一点要注意因为继承只能是一个,接口是可以实现多个的,实际情况还是要根据当前业务需求来确定。

守护线程

简介
守护线程存在就是为那些非守护线程服务的,守护线程类似于进程中的无关紧要的东西,他依赖与整个进程运行。由于守护线程终止是自身无法控制的,所有千万不要把不能被中断的业务交给它去执行,例如IO相关的操作,因为这样很有可能会造成IO资源无法被关闭

守护线程作用
就用Java GC垃圾回收线程为来说,GC线程就是一个经典的守护线程,当我们程序中没有任何需要运行的线程时,将不会这产生垃圾了,垃圾回收也就无事可干了,所以GC垃圾回收线程是JVM上最后一个线程时,垃圾回收线程会自己离开。它始终处于最低级别的状态中运行,用来实时监控管理是否有可回收垃圾资源

应用场景
来为其他线程提供服务支持,这任何情况下,这个线程被关闭后都是可以很正常的,不会造成任何其他的影响,就可以做为守护线程来使用。反之如果这个线程这进行操作时不能被中断,例如数据的更新,IO流相关的操作,则不能做为守护线程。

设置守护线程
创建线程后调用当前线程的setDaemon()方法,例如thread.setDaemon(true),线程想设置为守护线程的话务必要使用thread.start()方法之前设置,否则会出现java.lang.IllegalThreadStateException异常

你可能感兴趣的:(Java,java,多线程)