Java中线程状态的转换

Java线程的六种状态

Java中定义的线程状态有六种,这个是在JDK代码中明确定义了的,他和我们在操作系统里面学的线程状态略有出入。操作系统中只有新建,就绪,运行,阻塞,结束五种状态。其实就是把操作系统中规定的阻塞状态细化成了阻塞,等待,计时等待,而将就绪和运行状态统一成了可运行状态,实际代码执行时可运行状态里面确实有个系统调度的过程,调度成功执行了在运行状态,否则在就绪状态。
以下是六种状态的状态转换图:

image.png

初始状态:
我们可以通过new一个Thread或者实现Runnable,Callable接口来生成一个线程,线程new出来就进入了初始状态。
可运行状态:
线程的sleep()结束,其他线程join()结束可以让线程从等待状态进入可运行状态。
执行线程的start()方法可以让线程进入可运行状态。
阻塞的线程拿到锁之后,也可以进入可运行状态。
细分来说,进入可运行状态只是代表有资格运行,需要线程调度挑选到才会真正运行,否则是处于就绪状态的。
阻塞状态:
进入synchronized修饰的代码块或者线程没有获得锁的时候就是阻塞状态,阻塞状态在获取锁之后不释放,其他线程是没法获取锁去执行的,这是他和等待状态最大的区别。
等待状态:
线程执行sleep()或其他线程的join()方法会让当前线程处于等待状态,当然还有Object类的wait()和LockSupport中的方法,等待状态要回到可运行状态必须要通过notify(),notifyAll()或者unpark()方法唤醒。
计时等待状态:
线程执行sleep()或其他线程的join()方法会让当前线程处于等待状态,当然还有Object类的wait()和LockSupport中的方法,这些方法都会制定超时时间,和等待状态不同的是他不用等待被唤醒,达到超时时间后会自动唤醒,当然如果提前唤醒也是可以。
结束状态:
当线程的run()方法完成或者主线程的main()方法完成时候会进入结束状态,一旦线程结束了,就不能再次启用。如果在一个终止状态的线程上调用start()方法会抛出异常,具体说是java.lang. IllegalThreadStateException.

相关方法执行的区别

最后需要了解一下几个,或者说几对方法执行的区别,保证我们在使用时的正确选择:
start()和run()方法:
两个都是Thread类提供的方法,Thread的start()方法在内部调用了run()方法,执行start()方法会启动一个线程,而run()方法里面描述的只是执行线程的任务代码,仍然在当前线程执行。
只有调用了start()方法,才会表现出多线程的特性,他会让不同线程里面的run方法里面的代码交替执行。如果只是调用run()方法,实际执行还是一个线程run()方法里面的代码执行完成后再执行其他线程中定义的run()方法,也就是说本质还是一个线程“串行”执行代码。
sleep()和wait()方法:
最主要是sleep方法没有释放锁(或者说不释放monitor),而wait方法释放了锁(或者说释放了monitor),使得其他线程可以使用同步控制块或者方法。
另外sleep()方法是Thread类中的方法,而wait()方法是Object类中的方法。
notify()和notifyAll()方法:
notify()方法唤醒的是在这个对象监视器上等待的单个线程,具体选择哪个线程是任意的,而notifyAll()方法会唤醒在此对象监视器上所有等待的线程。
你会在很多Java编码规范里告诉你能用notifyAll()的就用notifyAll(),而不是用notify()方法,除非自己明确知道此处只要唤醒任意一个线程即可。

你可能感兴趣的:(Java中线程状态的转换)