【第一章】 图解Java并发编程
Java线程的基本操作
-
yield
操作:yield操作,在基于时间片轮转的cpu调度算法中,用来放弃当前时间片 -
sleep
操作:sleep操作分为三种情况-
-
普通sleep:在指定时间内放弃cpu使用权,不释放同步锁
-
sleep(0)
: 作用与yield相同 -
sleep被中断:抛出中断异常
-
-
-
中断操作:JDK为Thread类预留了三个中断标识符,分别为:
-
public void interrupt()
:-
如果当前线程在wait sleep join中,则会抛出异常并清空中断状态
-
如果当前线程正常运行与IO无关,则对中断标志设置为true。需要自己捕捉
-
-
public Boolean isInterrupted()
-
public static Boolean interrupted()
:返回中断状态,并清空中断状态 -
park
操作:线程在调用park阻塞被中断后,不会抛出异常
-
park/wait/suspend对比 设计思路
Java线程间通信(决定线程执行顺序)提供了三种方式,分别为park unpark/wait notify /suspend resume
区别如下:
-
suspend/resume: 该方法是线程对象的方法,直接操作线程。如果线程阻塞时还未来及释放某个对象的锁,那么则会导致需要该锁的对象一直阻塞下去
-
wait/notify: 方法需要一个对象来作为锁标志,这样只要编程时保证操作完其他对象的锁再释放锁对象的锁,即可一定程度上避免死锁问题。但是假如先执行了notify方法,那么wait方法将永远阻塞,导致死锁
-
park/unpark:方法基于许可机制。即unpark将许可一次park操作。即便是先执行了unpark,park操作也会得到许可而不被阻塞。注意,unpark的许可是一次性的,不论park前调用多少次unpark,只会许可一次park操作。
思路总结:
suspend/resume 最原始,直接操作线程,存在死锁问题,因此引入wait/notify来解决死锁问题。但是后者执行顺序不确定仍然可能导致死锁,因此使用park/unpark的认证机制来避免死锁。
Join操作
Join操作主要用来等待其他线程完成任务,并由JVM在线程结束时自动调用notifyAll方法唤醒调用Join的线程。
thread2.start();// 执行一些操作
thread3.start();// 执行一些操作
thread1.start();
thread1.join();
System.out.println("Thread all ended")
如代码所示,此时thread1将对thread2、thread3进行等待,阻塞直到两个线程结束为止。
Join操作实现原理
Join操作最终将调用join(long timeMills)
。这个方法有三个策略
-
if time < 0 抛出参数不合法异常
-
if time == 0 则永久等待,直到被终止的线程自动通知
-
if time > 0 那么将进入等待状态,给定时间后结束等待。