CountDownLatch
在学习线程基本知识的时候,学习过一个线程的join方法,该方法就是让当前线程等待,直到当前线程中调用了join方法的线程执行完毕,再执行本线程。加入在导入一个Excel的时候,有多个sheet,那么可能我们就考虑用多个线程分别读取sheet然后保存数据库,再记录日志,然后通知用户导入成功。先看join实现:
public class JoinTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch ct = new CountDownLatch(3);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() +"导入成功");
Thread.currentThread().sleep(2000);
System.out.println(Thread.currentThread().getName() +"记录日志");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() +"导入成功");
Thread.currentThread().sleep(2000);
System.out.println(Thread.currentThread().getName() +"记录日志");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() +"导入成功");
Thread.currentThread().sleep(2000);
System.out.println(Thread.currentThread().getName() +"记录日志");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "t3");
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println("导入成功。。。。。。。");
}
}
这里假设每次记录日志需要2秒时间。线程休眠两秒。执行结果:
t2导入成功
t3导入成功
t1导入成功
t3记录日志
t1记录日志
t2记录日志
导入成功。。。。。。。
结果用户一说,哎呀你这系统太慢了。一分析,原来日志记录花了不少时间,那就想,只要数据导入成功就通知用户,然后用户该干嘛干嘛去,我们慢慢记录日志。join就不好实现了。JAVA并发包下提供了一个CountDownLatch可以实现这个要求
CountDownLatch
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。CountDownLatch是个辅助类,可以简单理解为计数器,就是说某个线程在做某事情之前,先规划要前面先做了那几个事情,才能做。我们来实现上面的功能:
public class CountDownLatchTest {
static CountDownLatch ct = new CountDownLatch(3);
public static void main(String[] args) throws InterruptedException {
new Thread(new ImportExcel(), "t1").start();
new Thread(new ImportExcel(), "t2").start();
new Thread(new ImportExcel(), "t3").start();
ct.await();
System.out.println("导入成功。。。。。。。");
}
static class ImportExcel implements Runnable{
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() +"导入成功");
ct.countDown();
Thread.currentThread().sleep(2000);
System.out.println(Thread.currentThread().getName() +"记录日志");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
t2导入成功
t3导入成功
t1导入成功
导入成功。。。。。。。
t2记录日志
t3记录日志
t1记录日志
可以看到,只要导入成功就可以马上通知用户,然后执行各自的日志记录。