多线程之同步器:
假设有A,B 两个任务需要执行,A耗时3分钟,B耗时4分钟
常规方法是
A();
B() ;
... 总耗时7分钟
但是如果想缩短时间,且A B在执行中没有对同一资源的争夺,那么
可以开启两个线程,分别执行A,B Java提供了三种创建线程的方法
1 通过实现Runnable 接口;
2 通过继承Thread 类本身;
2 通过Callable和Future 创建线程。
此外,spring 可以通过TaskExcutor 任务执行器来实现多线程
线程1{ A() }
线程2{ B() }
...总耗时4分钟
进程会在开启两个进程执行A ,B后,继续执行接下来的代码而不必等待A B结束。
在一些情况下,我们接下来的代码(方法C)可能要用到A B 计算后的结果,那么该怎么设置程序等待A B 都运行结束呢?
线程同步器完美解决~
在JDK1.5以后,java.util.concurrent包提供了两个工具类CounDownLatch类和CyclicBarrier类。
CountDownLatch是一个同步计数器,能够保证在其他线程完成某一个业务操作前,当前线程一直处于等待/阻塞状态。具体来说,这个计数器将会从给定的某一个数值count开始,通过countDown()方法的调用进行倒数。当执行某一次countDown()操作后,计数器的count数值等于0,所有调用了await()方法的线程,就解除等待/阻塞状态继续执行。
// 同步计数器从2开始计数
finalCountDownLatch countDownLatch =newCountDownLatch(2);
// 启动子线程,处理A B
Thread childThreadA =newThread() {
@Override
public void run(){
synchronized(this){
try{
A();
}catch(InterruptedException e) {
TestCountDownLatch.LOGGER.error(e.getMessage(), e);
}
}
// 完成业务处理过程,计数器-1
countDownLatch.countDown();
}
};
Thread childThreadB =newThread() {
@Override
public void run(){
synchronized(this){
try{
B();
}catch(InterruptedException e) {
TestCountDownLatch.LOGGER.error(e.getMessage(), e);
}
}
// 完成业务处理过程,计数器-1
countDownLatch.countDown();
}
};
childThreadA.start();
childThreadB.start();
// 等待所有子线程的业务都处理完成(计数器的count为0时)
countDownLatch.await();
c();
CyclicBarrier也是同步计数工具,不同的是CyclicBarrier的计数是循环进行的,而且也不需要向CountDownLatch那样显示的调用countDown进行减一操作。当CyclicBarrier的计数周期设置为n的时候,每当有n个进程进入阻塞等待,CyclicBarrier就解除这n个进程的阻塞状态。所以可以理解为CyclicBarrier的计数功能是可以重复使用的。
网友评论