方法join的使用
1,主线程启动子线程后,如果主线程项等子线程执行完成后再结束,就要用到join()方法了。
测试代码:
public class JoinThread extends Thread{
@Override
public void run() {
try {
int value = (int)(Math.random()*10000);
System.out.println(value);
Thread.sleep(value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class RunTest {
public static void main(String[] args) {
try {
JoinThread jt = new JoinThread();
jt.start();
jt.join();
System.out.println("after joinThread finish,print this");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
3231
after joinThread finish,print this
方法join的作用是使所属的线程对象t正常执行run()方法中的任务,而使当前线程m进入无限期阻塞,等待t线程运行结束销毁后在继续执行m线程后面的代码。
Join方法具有使线程排队运行的作用,类似同步的运行结果。与synchronized方法的区别:join方法实际是一个synchronized方法,内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监视器”机制做同步。
2,在join的过程中,如果当前线程对象被中断,则当前线程出现异常。
测试代码:
public class ThreadA extends Thread{
@Override
public void run() {
for(int i=0; i<Integer.MAX_VALUE; i++){
String str = new String();
Math.random();
}
}
}
public class ThreadB extends Thread{
@Override
public void run() {
try {
ThreadA ta = new ThreadA();
ta.start();
ta.join();
System.out.println("thread B run end.");
} catch (InterruptedException e) {
System.out.println("thread B InterruptedException.");
e.printStackTrace();
}
}
}
public class ThreadC extends Thread{
private ThreadB tb;
public ThreadC(ThreadB tb){
super();
this.tb = tb;
}
@Override
public void run() {
tb.interrupt();
}
}
public class RunTest {
public static void main(String[] args) {
try {
ThreadB tb = new ThreadB();
tb.start();
Thread.sleep(500);
ThreadC tc = new ThreadC(tb);
tc.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
thread B InterruptedException.
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Unknown Source)
at java.lang.Thread.join(Unknown Source)
at ThreadB.run(ThreadB.java:9)
Join方法和interrupt方法彼此遇到,就会出异常。
3,join(long),可以设定等待的时间。
跟Thread.sleep(long)方法的区别,Thread.sleep(long)方法不会释放锁。
测试代码,验证:Thread.sleep(long)方法不会释放锁。
public class ThreadA extends Thread{
private ThreadB tb;
public ThreadA(ThreadB tb){
super();
this.tb = tb;
}
@Override
public void run() {
try {
synchronized(tb){
tb.start();
System.out.println("ta run begin time ="+System.currentTimeMillis());
Thread.sleep(6000);
System.out.println("ta run end time ="+System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadB extends Thread{
@Override
public void run() {
try {
System.out.println("tb run begin time ="+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("tb run end time ="+System.currentTimeMillis());
} catch (InterruptedException e) {
System.out.println("thread B InterruptedException.");
e.printStackTrace();
}
}
synchronized public void tbService(){
System.out.println("print tb service timer="+System.currentTimeMillis());
}
}
public class ThreadC extends Thread{
private ThreadB tb;
public ThreadC(ThreadB tb){
super();
this.tb = tb;
}
@Override
public void run() {
tb.tbService();
}
}
public class RunTest {
public static void main(String[] args) {
try {
ThreadB tb = new ThreadB();
ThreadA ta = new ThreadA(tb);
ta.start();
Thread.sleep(2000);
ThreadC tc = new ThreadC(tb);
tc.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
ta run begin time =1516180072939
tb run begin time =1516180072939
tb run end time =1516180077940
ta run end time =1516180078940
print tb service timer=1516180078940
可以看到,print tb service timer=1516180078940 这句没有马上输出,而是等到ta的sleep时间到了之后才输出。
因为ta的sleep方法一直持有tb对象的锁,时间是6秒,所以tc只有在6s后,ta释放了tb锁后,才能调用tb的同步方法synchronized public void tbService(){}
修改ThreadA的run方法,把sleep(6000)改成tb.join(),运行结果:
tb run begin time =1516180439457
ta run begin time =1516180439457
print tb service timer=1516180441472
tb run end time =1516180444457
ta run end time =1516180444457
由于join方法释放了锁,tbService方法可以马上执行。