代码地址:https://github.com/xianzhixianzhixian/thread.git
join()方法的使用
1、join()方法的用途是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。
2、join()和synchronized的区别:join()在内部使用的是wait()方法进行等待,而synchronized关键字使用的是“对象监视器”原理作为同步。join()执行后会立马释放锁,而synchronized则会持有锁直到运行结束。
3、在join的过程中,如果当前线程对象被中断,则当前线程出现java.lang.InterruptedException异常。
4、join(long)和sleep(long)的区别:join(long)的内部是由wait(long)实现的,所以join(long)争抢到锁执行后会立刻释放锁,而Thread.sleep(long)则会使线程睡眠long毫秒后执行完相应的代码后释放锁。
5、join(long)和Thread.start()在同一个代码块中时,join(long)大部分先运行。
join(long)后面的代码提前运行示例及原因
ThreadA.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-07 21:34
*/
public class ThreadA extends Thread {
private ThreadB b;
public ThreadA(ThreadB b) {
this.b = b;
}
@Override
public void run() {
try {
synchronized (b) {
System.out.println("begin A ThreadName="+
Thread.currentThread().getName()+" "
+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("end A ThreadName="+
Thread.currentThread().getName()+" "
+System.currentTimeMillis());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
ThreadB.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-07 21:34
*/
public class ThreadB extends Thread {
@Override
synchronized public void run() {
try {
System.out.println("begin B ThreadName="+
Thread.currentThread().getName()+" "
+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("end B ThreadName="+
Thread.currentThread().getName()+" "
+System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Run.java
/**
* 方法join()后面的代码提前运行示例(有时会出现这种情况)
* 这里涉及到join(long)和a、b线程争抢对象锁的问题
* @author: xianzhixianzhixian
* @date: 2019-01-07 21:38
*/
public class Run {
public static void main(String[] args) {
try {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
b.start();
b.join(2000);
System.out.println("main end "+System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
第一种情况:A线程运行完之后main中的语句执行完毕,B线程继续执行完毕
原因:
1、 b.join(2000)方法先抢到B锁, 然后将B锁进行释放;
2、ThreadA抢到锁,打印ThreadAbegin并且sleep(5000);
3、ThreadA打印ThreadA end, 并释放锁;
4、这时join(2000)和Tl订eadB争抢锁, 而join(2000)再次抢到锁, 发现时间已过, 释放锁后打印main end;
5、ThreadB抢到锁打印ThreadB begin;
6、5秒之后再打印ThreadBend。
第二种情况:A线程运行完之后,B线程继续执行完毕,main中的语句执行完毕
原因:
1、b.join(2000)方法先抢到B锁, 然后将B锁进行释放;
2、T比eadA抢到锁,打印TeadAbegin并且sleep(5000);
3、ThreadA打印T缸eadAend, 并释放锁;
4、这时join(2000)和ThreadB争抢锁,而ThreadB抢到锁后执行sleep(5000)后释放锁;
5、main end在最后输出。
第三种情况:实验不出来,截书上图吧