正常环境下,每个子线程完成各自的任务就可以竣事了。不外有的时候,我们但愿多个线程协同事情来完成某个任务,这时就涉及到了线程间通信了。
本文涉及到的常识点:thread.join(), object.wait(), object.notify(), CountdownLatch, CyclicBarrier, FutureTask, Callable 等。
本文涉及代码:
https://github.com/wingjay/HelloJava/blob/master/multi-thread/src/ForArticle.java
下面我从几个例子作为切入点来讲授下 Java 里有哪些要领来实现线程间通信。
如何让两个线程依次执行?
假设有两个线程,一个是线程 A,另一个是线程 B,两个线程别离依次打印 1-3 三个数字即可。我们来看下代码:
java; gutter: true">private static void demo1() { Thread A = new Thread(new Runnable() { @Override public void run() { printNumber("A"); } }); Thread B = new Thread(new Runnable() { @Override public void run() { printNumber("B"); } }); A.start(); B.start(); }
个中的 printNumber(String) 实现如下,用来依次打印 1, 2, 3 三个数字:
private static void printNumber(String threadName) { int i=0; while (i++ < 3) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName + "print:" + i); } }
这时我们获得的功效是:
B print: 1 A print: 1 B print: 2 A print: 2 B print: 3 A print: 3
可以看到 A 和 B 是同时打印的。
那么,假如我们但愿 B 在 A 全部打印 完后再开始打印呢?我们可以操作 thread.join() 要领,代码如下:
private static void demo2() { Thread A = new Thread(new Runnable() { @Override public void run() { printNumber("A"); } }); Thread B = new Thread(new Runnable() { @Override public void run() { System.out.println("B 开始期待 A"); try { A.join(); } catch (InterruptedException e) { e.printStackTrace(); } printNumber("B"); } }); B.start(); A.start(); }
获得的功效如下:
B 开始期待 A A print: 1 A print: 2 A print: 3 B print: 1 B print: 2 B print: 3
所以我们能看到 A.join() 要了解让 B 一直期待直到 A 运行完毕。
那如何让 两个线程凭据指定方法有序交错运行呢?
照旧上面谁人例子,我此刻但愿 A 在打印完 1 后,再让 B 打印 1, 2, 3,最后再回到 A 继承打印 2, 3。这种需求下,显然 Thread.join() 已经不能满意了。我们需要更细粒度的锁来节制执行顺序。
这里,我们可以操作 object.wait() 和 object.notify() 两个要领来实现。代码如下:
/** * A 1, B 1, B 2, B 3, A 2, A 3 */ private static void demo3() { Object lock = new Object(); Thread A = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { System.out.println("A 1"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("A 2"); System.out.println("A 3"); } } }); Thread B = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { System.out.println("B 1"); System.out.println("B 2"); System.out.println("B 3"); lock.notify(); } } }); A.start(); B.start(); }
打印功效如下:
A 1 A waiting… B 1 B 2 B 3 A 2 A 3
正是我们要的功效。
那么,这个进程产生了什么呢?