看到一个多线程的编程问题,如何让线程A、B、C顺序执行,即线程A执行完后,线程B开始执行,线程B执行完后,线程C开始执行。
我的实现想法是使用单线程的线程池,依次将RunableA、RunnableB、RunnableC三个Runnable submit()。答案给的是使用Thread的join()方法,编了个程序验证下:
package com.zn.jinma.test;
public class TestJoin {
public static class RunnableA implements Runnable {
@Override
public void run() {
System.out.println("A thread start to run threadId " + Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A thread runOver");
}
}
public static class RunnableB implements Runnable {
@Override
public void run() {
System.out.println("B thread start to run threadId " + Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B thread runOver");
}
}
public static class RunnableC implements Runnable {
@Override
public void run() {
System.out.println("C thread start to run threadId " + Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C thread runOver");
}
}
public static class WorkerRunable implements Runnable {
@Override
public void run() {
System.out.println("worker runnable start to run threadId " + Thread.currentThread().getId());
System.out.println();
Thread threadA = new Thread(new RunnableA());
threadA.start();
try {
threadA.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("worker runnable threadA run over threadId " + Thread.currentThread().getId());
Thread threadB = new Thread(new RunnableB());
threadB.start();
try {
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("worker runnable threadb run over threadId " + Thread.currentThread().getId());
Thread threadC = new Thread(new RunnableC());
threadC.start();
try {
threadC.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("worker runnable threadC run over threadId " + Thread.currentThread().getId());
System.out.println();
System.out.println("worker runnable run over threadId " + Thread.currentThread().getId());
}
}
public static void main(String[] args) {
System.out.println("main thread thread start to run threadId " + Thread.currentThread().getId());
new Thread(new WorkerRunable()).start();
System.out.println("main thread run over");
System.out.println();
}
}
结果如下:
main thread thread start to run threadId 1
main thread run over
worker runnable start to run threadId 9
A thread start to run threadId 11
A thread runOver
worker runnable threadA run over threadId 9
B thread start to run threadId 12
B thread runOver
worker runnable threadb run over threadId 9
C thread start to run threadId 13
C thread runOver
worker runnable threadC run over threadId 9
worker runnable run over threadId 9
代码思路很简单,主线程中开启工作线程,工作线程中,依次创建线程A、B、C,分别调用它们的start()方法和join()方法。
分析下结果,主线程执行完毕就退出了,工作者线程启动后,线程A、B、C依次开始执行,都执行完后,工作者线程退出执行。
从结果可以看出ThreadA.join()方法的意思是:工作者线程需要等ThreadA执行完毕后,才开始执行。
那么这是如何实现的呢?
看下join()方法(android中):
/**
* Blocks the current Thread (<code>Thread.currentThread()</code>) until
* the receiver finishes its execution and dies.
*
* @throws InterruptedException if the current thread has been interrupted.
* The interrupted status of the current thread will be cleared before the exception is
* thrown.
* @see Object#notifyAll
* @see java.lang.ThreadDeath
*/
public final void join() throws InterruptedException {
synchronized (lock) {
while (isAlive()) {
lock.wait();
}
}
}
其中lock是Thread对象的一个final对象,声明如下:
/**
* The synchronization object responsible for this thread's join/sleep/park operations.
*/
private final Object lock = new Object();
这样看来join()的方法非常简单,通过ThreadA.lock.wait()方法将join()方法执行所在线程(工作者线程,非ThreadA)阻塞,等到ThreadA执行完毕,ThreadA通过lock.notifyAll()方法将工作者线程唤醒(这里从哪里得出的结论?)工作者线程里isAlive()的判断为false,退出while循环,join()方法执行完毕。