**
* @PackageName:com.netty.obj.demo5 Description
* JOIN
* @author:
* @date:2022/1/12
*/
public class JoinCountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
//1 创建一个线程解析sheet1
Thread parser1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("sheet1 parser finish");
}
});
//2 创建一个线程解析sheet2
Thread parser2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("sheet2 parser finish");
}
});
//3.启动线程1,2
parser1.start();
parser2.start();
//4.调用线程的join方法,主线程main需要等待 线程 parser1,parser2执行完成后才往后执行主线程
parser1.join();
parser2.join();
System.out.println("all parser finish");
}
}
来看看join方法的源码:
public final void join() throws InterruptedException {
join(0);
}
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
接下来看看方案2的实现方式:CountDownLatch
**
* @PackageName:com.netty.obj.demo5.d1 Description
* @author: 等待多线程完成的CountDownLatch
* @date:2022/1/12
*/
public class CountDownLatchTest {
static CountDownLatch c = new CountDownLatch(2);
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("parser1 finish");
c.countDown();
System.out.println("parser1 finish");
c.countDown();
}
}).start();
c.await();
System.out.println("all parser finish");
}
}
CountDownLatch
的构造函数接收一个
int
类
型的参数作
为计
数器,如果你想等待
N
个点完
成,
这
里就
传
入
N
。
当我
们调
用
CountDownLatch
的
countDown
方法
时
,
N
就会减
1
,
CountDownLatch
的
await
方法
会阻塞当前
线
程,直到
N
变
成零。由于
countDown
方法可以用在任何地方,所以
这
里
说
的
N
个
点,可以是
N
个
线
程,也可以是
1
个
线
程里的
N
个
执
行步
骤
。用在多个
线
程
时
,只需要把
这
个
CountDownLatch
的引用
传递
到
线
程里即可。
如果有某个解析
sheet
的
线
程
处
理得比
较
慢,我
们
不可能
让
主
线
程一直等待,所以可以使
用另外一个
带
指定
时间
的
await
方法
——await
(
long time
,
TimeUnit unit
),
这
个方法等待特定
时
间
后,就会不再阻塞当前
线
程。
join
也有
类似的方法。--摘自Java并发编程的艺术
CountDownLatch 源码方法:
使当前线程等待,直到闩锁倒计时到零,除非线程是被中断interrupt
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
经过指定的等待时间使当前线程等待,直到闩锁倒计时到
零,除非线程是中断interrupt
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.tonanos(timeout));
}
递减闩锁计数,当计数为零时释放所有等待的线程
public void countDown() {
sync.releaseShared(1);
}
返回当前计数
public long getCount() { return sync.getCount(); }
总结:本节内容案例主要来至《 Java并发编程的艺术》,通过学习作者的案例变通为自己的理解,可能在业务开发中会用到此工具



