方法join的作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程Z进行无限期的阻塞,等待线程X销毁后再继续执行线程Z后面的代码。一般用于子线程先执行完毕再继续执行主线程的情况。
但是join方法后面的代码会不会提前执行呢?看下面的代码
1 public class ThreadA extends Thread { 2 3 private ThreadB threadB; 4 5 public ThreadA(ThreadB threadB) { 6 super(); 7 this.threadB = threadB; 8 } 9 10 @Override 11 public void run() { 12 synchronized (threadB) { 13 System.out.println("begin A ThreadName=" + Thread.currentThread().getName()); 14 try { 15 Thread.sleep(5000); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 System.out.println("end A ThreadName=" + Thread.currentThread().getName()); 20 } 21 } 22 23 24 }
1 public class ThreadB extends Thread{ 2 @Override 3 public void run() { 4 System.out.println("begin B ThreadName=" + Thread.currentThread().getName()); 5 try { 6 Thread.sleep(5000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 System.out.println("end B ThreadName=" + Thread.currentThread().getName()); 11 } 12 }
1 public class Run { 2 public static void main(String[] args) throws InterruptedException { 3 ThreadB threadB = new ThreadB(); 4 ThreadA threadA = new ThreadA(threadB); 5 threadA.start(); 6 threadB.start(); 7 threadB.join(2000); 8 System.out.println("main thread"); 9 10 } 11 }
运行几次后会发现,大部分时候结果是
但也会出现如下结果
join方法后面的代码提前执行了,这是怎么一回事呢?我们修改Run.java,将join方法注释掉,再次运行,发现结果如下
通过多次运行Run.java文件后,可以发现一个规侓:main end往往都是第一个打印的。所以可以完全确定地得出一个结论:方法join(2000)大部分是先运行的,也就是先抢到ThreadB的锁,然后快速进行释放。
代码运行步骤如下:
1)b.join(2000)方法先抢到B锁,然后将B锁进行释放;
2)ThreadA抢到锁,打印 ThreadA begin 并且 sleep(5000);
3)ThreadA 打印 ThreadA end,并释放锁;
4)这时join(2000)和ThreadB争抢锁,而join(2000)再次抢到锁,发现时间已过,释放锁;
5)ThreadB 抢到锁打印 ThreadB begin,main线程也异步打印main end;
6)5秒之后再打印ThreadB end。
这样就会出现join方法后面的代码提前执行的情况。
原文地址:https://www.cnblogs.com/le-le/p/12074712.html
时间: 2024-09-30 06:32:16