Java基础之并发编程(一)
一、Java线程的6种状态:
1)New(新生);线程被创建但尚未执行,如:Thread thread = new Thread();
2)Runnable(可运行);一旦调用thread.start()方法,线程即进入Runnable状态。此时,一个可运行线程可能处理运行状态也可能没有运行(Java规范说明没有将它作为一个单
独状态。一个运行中的线程仍然处于可运行状态)。一旦一个线程开始运行,它不必始终保持在运行。事实上,运行中的线程可能会被中断,目的是让其他线程获得运行的机会。
现在的桌面及服务器操作系统均使用抢占式调度方法,当给线程分配的时间片用完时运行权即被让度给其他线程(按照优先级选择);但手机等设备使用协作式调度,一个线程只
有在调用thread.yield()方法、被阻塞或等待时才失去控制权。
3)Blocked(被阻塞);线程由于某种原因暂停放弃或丢掉了CPU的使用权,它暂时不执行,即进入Blocked状态。被阻塞状态下不执行任何代码且只消耗极少的资源,直到线程调度
器重新激活它(即由Blocked状态进入Runnable才有机会被再次执行)。当线程试图获得一个内部的对象锁(synchy),而该锁被其他线程所持有,则该线程进入阻塞状态;当
其他线程放弃该锁,并且线程调度器允许该线程持有时,该线程变成非阻塞状态。
4)Waiting(等待执行);当线程等待其他线程向调度器通知一个条件时,该线程进入Waiting状态。在调用Object.wait()或Thread.join(),或是等待java.util.concurrent库中的
Lock或Condition时,就会出现这种情况。实际上,被阻塞与等待状态存在很大的不同。
5)Timed Waiting(计时等待);调用线程的带有超时参数的方法将使线程进入Timed Waiting状态,这一状态将持续到超时或接到适当的通知。相应的带有超时参数的方法有:
Thread.sleep()、Object.wait()、Thread.join()、Lock.tryLock()、Condition.await()(计时版)等。
6)Terminated(被终止);或线程因为run方法执行完而自然死亡,或者因为一个没有捕获的异常终止了run方法而意外死亡,线程即进入Terminated(或Dead)状态。可调用
thread.stop()方法抛出ThreadDeath异常来杀死一个线程(该方法已过时)。
二、线程的生命周期及不同状态切换
图1 线程生命周期示意图
相关方法说明:
1)yield()方法尝试让出所占用的CPU资源,让其他线程获得运行的机会,对操作系统来说是一个信号,不一定会立即切换线程。在实际开发的测试阶段较多使用yield()方法
频繁切换线程以更多地暴露多线程相关的Bug;
2)sleep()方法进入的阻塞状态不会释放对象的锁,即中止执行代码并等待给定的时间,所以不要把sleep()方法放在synchronized代码块中,否则将造成其他需要获取该对
象锁的线程长时间处于等待状态;
3)join()方法则是主线程等待子线程执行完成后再往下执行。
4)interrupt()方法向被调用的线程发起中断请求。如线程A通过调用线程B的interrupt()方法来发出中断请求,以获得运行机会,线程B可能响应该请求也可能忽略。