Java多线程--wait和join

首先从公司一道笔试题开始

 1 package test;
 2 
 3 public class Test implements Runnable {
 4 
 5     public int i = 0;
 6 
 7     @Override
 8     public void run() {
 9         try {
10             Thread.sleep(1000);
11         } catch (InterruptedException e) {
12             // TODO Auto-generated catch block
13             e.printStackTrace();
14         }
15         i = 10;
16     }
17 
18     public static void main(String[] args) {
19         try {
20             Test t = new Test();
21             Thread th = new Thread(t);
22             th.start();
23             th.join();
24             System.out.println(t.i);
25         } catch (Exception ex) {
26 
27         }
28 
29     }
30 }

 问23行代码怎么写,才能让24行打印出10?

不少笔试者会选t.wait()或者th.wait()!

面试的时候问他为什么,他具体也说不清楚,感觉就是见过这个wait方法,但是wait方法的含义确一知半解。

wait 是什么意思呢?我举例子啊,比如我想让本线程放弃当前对象锁,说直白点就是让别的对象进入同步块

 1 package test;
 2 
 3 public class Test implements Runnable {
 4 
 5     public Object i = new Object();
 6 
 7     @Override
 8     public void run() {
 9         synchronized (i) {
10             System.out.println(Thread.currentThread().getName()+"enter ");
11 //            i.notify();
12             try {
13                 i.wait();
14             } catch (InterruptedException e) {
15                 // TODO Auto-generated catch block
16                 e.printStackTrace();
17             }
18             System.out.println(Thread.currentThread().getName()+"out ");
19         }
20     }
21 
22     public static void main(String[] args) {
23         try {
24             Test t = new Test();
25             Thread th1 = new Thread(t);
26             Thread th2 = new Thread(t);
27             th1.start();
28             th2.start();
29             
30             
31         } catch (Exception ex) {
32 
33         }
34 
35     }
36 }

如上例,你会看到输出

Thread-0enter
Thread-1enter

不会看到

Thread-1out
Thread-0out

因为Thread-0 先获得了Object i 锁,然后运行到13行,释放了该锁,

这个时候Thread-1就获得了Object i 锁,进入了同步代码块,然后同样运行13行,也释放了该锁。

这个时候在有两个线程Thread-0和Thread-1等待获得Object i 锁,由于代码中没有调用i.notifyAll(),所以这个程序永远不会退出。

但是如果打开注释11行,那么你将会看到结果

Thread-0enter
Thread-1enter
Thread-0out

因为Thread-0 先获得了Object i 锁,然后运行到13行,释放了该锁,

这个时候Thread-1就获得了Object i 锁,进入了同步代码块,运行到11行,i.notify(),

那么这个意思就是说别的等待i锁的线程可以唤醒了,一旦我(Thread-1)释放锁(13行调用wait()),那么Thread-0就可以获得i锁继续执行了。

此程序中没有在Thread-1 释放i锁(wait())之后notify,所以永远不会看到Thread-1out

再回到这个题目,我们的意思是让主线程等待所有子线程执行完毕 ,再执行。更何况笔试题中没有锁对象。更别提wait()了。

所以,此处应该用th.join();   Thread.join()方法会阻塞主线程继续向下执行。

 1 public class TestThread extends Thread  
 2 {  
 3     private CountDownLatch countDownLatch;  
 4           
 5     public TestThread(CountDownLatch countDownLatch)  
 6     {  
 7         this.countDownLatch = countDownLatch;  
 8     }  
 9 
10     public void run()  
11     {  
12         System.out.println(this.getName() + "子线程开始");  
13         try  
14         {  
15             // 子线程休眠五秒  
16             Thread.sleep(5000);  
17         }  
18         catch (InterruptedException e)  
19         {  
20             e.printStackTrace();  
21         }
22 
23         System.out.println(this.getName() + "子线程结束");
24           
25         // 倒数器减1
26         countDownLatch.countDown();
27     }
28 }
 1 public class Main
 2 {
 3     public static void main(String[] args)
 4     {
 5         long start = System.currentTimeMillis();
 6         
 7         // 创建一个初始值为5的倒数计数器
 8         CountDownLatch countDownLatch = new CountDownLatch(5);
 9         for(int i = 0; i < 5; i++)
10         {
11             Thread thread = new TestThread(countDownLatch);
12             thread.start();
13         }
14         
15         try
16         {
17             // 阻塞当前线程,直到倒数计数器倒数到0
18             countDownLatch.await();
19         }
20         catch (InterruptedException e)
21         {
22             e.printStackTrace();
23         }
24         
25         long end = System.currentTimeMillis();
26         System.out.println("子线程执行时长:" + (end - start));
27     }
28 }
原文地址:https://www.cnblogs.com/fengjian/p/4631724.html