目录
1 wait()被中断的过程
1.1 代码示例
开启两个线程,一个线程等待,另一个线程获取锁后打印信息,打印期间对等待线程进行中断,通过打印的控制台信息来查看中断过程。
public class Test3 {
static Object lock = new Object(); // 同步锁和等待锁
public static void main(String[] args) throws InterruptedException {
MyThread myThread1 = new MyThread("线程1", true);
MyThread myThread2 = new MyThread("线程2", false);
myThread1.start();
Thread.sleep(100); // 给myThread1启动留时间
myThread2.start(); // 给myThread2启动留时间
Thread.sleep(100);
System.out.println(myThread1.getName()+":状态为"+myThread1.getState());
myThread1.interrupt();
Thread.sleep(100); // 给中断操作留时间
System.out.println(myThread1.getName()+":被中断");
System.out.println(myThread1.getName()+":状态为"+myThread1.getState());
}
private static class MyThread extends Thread{
volatile boolean wait; // 等待标志,true则线程会在run()中等待
MyThread(String name, boolean wait){
super(name);
this.wait = wait;
}
@Override
public void run() {
synchronized (lock){
if (wait){
try {
lock.wait();
} catch (InterruptedException e) {
System.out.println(this.getName()+":被中断后的打印信息");
}
}else{
int i = 3;
while (i-- > 0){ // 每隔1s打印,打印3次
try {
Thread.sleep(1000);
System.out.println("printInfo");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(this.getName()+":释放锁");
}
}
}
}
打印结果如下:
线程1:状态为WAITING
线程1:被中断
线程1:状态为BLOCKED
printInfo
printInfo
printInfo
线程2:释放锁
线程1:被中断后的打印信息
线程1:释放锁
Process finished with exit code 0
1.2 结果分析
显然,对wait的线程进行中断首先将线程从等待队列移到阻塞队列(线程状态由WAITING——>BLOCKED),然后等待锁被释放,释放后才抛出InterruptedException,打印catch中的信息。
2 join()被中断过程
2.1 代码示例
在join线程执行期间,对joined线程进行中断。
public class Test4 {
public static void main(String[] args) throws InterruptedException {
MyThread join = new MyThread("join线程", false, null);
join.start();
MyThread interruptThread = null;
for (int i=1;i<=10;++i){ // 创建10个线程
MyThread joined = new MyThread("joined线程"+i, true, join);
joined.start();
if (i == 5){ // 中断第5个线程
interruptThread = joined;
}
}
Thread.sleep(1000); // 留出时间给join线程运行
interruptThread.interrupt();
System.out.println(interruptThread.getName()+":被中断");
}
private static class MyThread extends Thread{
boolean joined; // true表示该线程是joined线程,false为join线程
Thread joinThread;
MyThread(String name , boolean joined , Thread joinThread){
super(name);
this.joined = joined;
this.joinThread = joinThread;
}
@Override
public void run() {
if (joined){
try {
joinThread.join();
System.out.println(this.getName()+":被notify后的打印信息");
} catch (InterruptedException e) {
System.out.println(this.getName()+":被中断后的打印信息");
}
}else{
int i = 3;
while (i-- > 0){ // 每隔0.5s打印,打印3次
try {
Thread.sleep(500);
System.out.println(this.getName()+":printInfo");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
打印结果如下:
join线程:printInfo
joined线程5:被中断
joined线程5:被中断后的打印信息
join线程:printInfo
join线程:printInfo
joined线程10:被notify后的打印信息
joined线程6:被notify后的打印信息
joined线程2:被notify后的打印信息
joined线程1:被notify后的打印信息
joined线程9:被notify后的打印信息
joined线程7:被notify后的打印信息
joined线程3:被notify后的打印信息
joined线程8:被notify后的打印信息
joined线程4:被notify后的打印信息
Process finished with exit code 0
2.2 结果分析
显然,被中断的joined线程在join线程运行期间直接返回并抛出了InterruptedException。其实join()就相当于joined线程在synchronized中执行了join线程对象的wait(),因为join方法被synchronized关键字修饰了,执行join()必须获取到join线程对象这个锁,与wait()中断的过程一模一样。
在上面例子中,因为join线程对象没有在我们代码其它地方作为synchronized的锁被其它线程持有,所以joined线程5被中断之后能立刻获取锁从join()返回。Thread.join()如下:
public final synchronized void join(long millis) throws InterruptedException {
...
while (isAlive()) {
wait(0);
}
...
}