Thread Join 简单理解就是等待被调用join的线程先执行完,再自己执行;或者并发线程串行化。
不要轻易的使用join否则严重降低线程并发性能;jdk 并不建议使用join。
jdk 解释join原文:
public final void join() throws InterruptedException Waits for this thread to die. Throws: InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
demo:
package test;
public class ThreadA extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i < 5; i++){
System.out.printf("ThreadA " + "run i=" + i + "\n");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.printf("ThreadA " + "END..." + "\n");
}
}
package test;
public class ThreadB extends Thread{
private ThreadA at;
public ThreadB(ThreadA at){
this.at = at;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.printf("ThreadB " + "START..." + "\n");
System.out.printf("ThreadB " + "END..." + "\n");
try {
at.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package test;
public class threadMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadA at = new ThreadA();
ThreadB bt = new ThreadB(at);
at.start();
try {
Thread.sleep(2000);
System.out.println("main " + "run..." + "\n");
System.out.println("main " + "end..." + "\n");
bt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bt.start();
}
}
日志打印:
ThreadA run i=0
main run...
main end...
ThreadB START...
ThreadB END...
ThreadA run i=1
ThreadA run i=2
ThreadA run i=3
ThreadA run i=4
ThreadA END...
可以看出使用join之前的代码是可以先被执行的,所以join使用位置很重要。
代码调整如下:
package test;
public class ThreadA extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i < 5; i++){
System.out.printf("ThreadA " + "run i=" + i + "\n");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.printf("ThreadA " + "END..." + "\n");
}
}
package test;
public class ThreadB extends Thread{
private ThreadA at;
public ThreadB(ThreadA at){
this.at = at;
}
@Override
public void run() {
try {
at.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
System.out.printf("ThreadB " + "START..." + "\n");
System.out.printf("ThreadB " + "END..." + "\n");
}
}
package test;
public class threadMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadA at = new ThreadA();
ThreadB bt = new ThreadB(at);
at.start();
try {
//
Thread.sleep(2000);
bt.join();
System.out.println("main " + "run..." + "\n");
System.out.println("main " + "end..." + "\n");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bt.start();
}
}
日志打印:
ThreadA run i=0
main run...
main end...
ThreadA run i=1
ThreadA run i=2
ThreadA run i=3
ThreadA run i=4
ThreadA END...
ThreadB START...
ThreadB END...
为什么main还是早于bt执行,在于main中先调用join然后bt.start;如果调用join 的时候线程没有运行join是不生效的。
main做修改:
package test;
public class threadMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadA at = new ThreadA();
ThreadB bt = new ThreadB(at);
at.start();
bt.start();
try {
//
Thread.sleep(2000);
System.out.println("main sleep over, and bt join.");
bt.join();
System.out.println("main " + "run..." + "\n");
System.out.println("main " + "end..." + "\n");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
日志打印:
ThreadA run i=0
main sleep over, and bt join.
ThreadA run i=1
ThreadA run i=2
ThreadA run i=3
ThreadA run i=4
ThreadA END...
ThreadB START...
ThreadB END...
main run...
main end...