1、CountDownLatch:同步计数器
当CountDownLatch的count计数>0时,await()会造成线程阻塞,当使用countDown()让count-- == 0时,线程结束阻塞。 如果想让其他线程执行完指定程序,其他所有程序都执行结束后再执行,这时可以用CountDownLatch,但计数无法被重置,如果需要重置计数,请考虑使用 CyclicBarrier。下面demo演示了当所有线程执行完任务后。
public class CountDownLatchDemo implements Runnable {
private CountDownLatch begin;
//观察end的count为0时,会使当前线程退出阻塞
private CountDownLatch end;
//用来模拟子线程执行的任务
private int index = 10;
public CountDownLatchDemo(CountDownLatch begin, CountDownLatch end) {
this.begin = begin;
this.end = end;
}
//这里要使用同步synchronized
synchronized public void run(){
try {
begin.await();
index--;
System.out.println(Thread.currentThread().getName() + ":执行完任务了, index: " + index);
} catch (Exception e) {
e.printStackTrace();
} finally {
end.countDown();
}
}
public static void main(String[] args) throws InterruptedException {
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(10);
CountDownLatchDemo cdlDemo = new CountDownLatchDemo(begin, end);
System.out.println("所有线程开始执行任务....");
for (int i = 0; i < 10; i++) {
new Thread(cdlDemo).start();
}
//开始让所有线程工作
begin.countDown();
//
end.await();
System.out.println("所有线程完成任务,可以开始做其它想做的事 了....");
}
}
2、CyclicBarrier: 线程屏障的功能
可以协同多个线程,让多个线程在这个屏障前等到,直到所有线程都到达了这个屏障时,再一起执行后面的操作。下面demo创建11个线程,前面每一个线程使用await()都会使当前线程阻塞,直到最后一个线程使用await()会使11个线程全部退出阻塞。
public class CyclicBarrierDemo implements Runnable {
private CyclicBarrier cyclicBarrier;
private int index ;
public CyclicBarrierDemo(CyclicBarrier cyclicBarrier, int index) {
this.cyclicBarrier = cyclicBarrier;
this.index = index;
}
public void run() {
try {
System.out.println("index: " + index);
index--;
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
CyclicBarrier cyclicBarrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) {
new Thread(new CyclicBarrierDemo(cyclicBarrier, i)).start();
}
cyclicBarrier.await();
System.out.println("全部到达屏障....");
}
}
3、Exchanger:用来使两个线程交换数据。
当一个线程运行到exchange()方法时会阻塞,另一个线程运行到exchange()时,二者交换数据,然后执行后面的程序。
public class ExchangerDemo implements Runnable {
private Exchanger
4、Semaphore:控制信号量的个数,构造时传入个数。总数就是控制并发的数量。
线程执行前用acquire()方法获得信号,执行完通过release()方法归还信号量。如果可用信号为0,acquire就会造成阻塞,等待release释放信号。作用就是只让指定个数的线程(随机选择或先来后到)并行。
public class SemaphoreDemo implements Runnable {
private Semaphore sema;
public SemaphoreDemo (Semaphore semaphore) {
this.sema = semaphore;
}
public void run() {
try {
sema.acquire();
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + ": 执行完: " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
sema.release();
}
}
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
SemaphoreDemo semaphoreDemo = new SemaphoreDemo(semaphore);
for (int i = 0; i < 10; i++) {
new Thread(semaphoreDemo).start();
}
}
}
5、Future:接口,FutureTask是它的实现类,配合线程池来一起工作,将任务交给线程池去处理。
public class FutureDemo {
public static void main(String[] args) throws Exception {
Future task = new FutureTask(new Callable() {
@Override
public Integer call() {
return 1+2+3+4;
}
});
new Thread((Runnable) task).start();
System.out.println("start.........");
TimeUnit.SECONDS.sleep(2);
System.out.println("result: " + task.get());
}
}
最后贴一个业务场景分别用CyclicBarrier和Future代码片段:
用CyclicBarrier实现
int size = executeMethods.length;
CyclicBarrier cyclicBarrier = new CyclicBarrier(size+1);
for (int i = 0; i < size; i++) {
threadPool.execute(new CheckItemsTask(
customerId, executeMethods[i], cyclicBarrier, CheckResultVO));
}
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
public class CheckItemsTask implements Runnable {
String EXECUTE_PREFIX = Constant.EXECUTE_METHOD_START_STR;
String SETTLE_PREFIX = Constant.SETTLE_METHOD_START_STR;
private CyclicBarrier cyclicBarrier;
private CheckResultVO checkResultVO;
private String methodName;
private Integer customerId;
SettleOrderService settleOrderService = SpringUtils.getBean(SettleOrderService.class);
Class c = settleOrderService.getClass();
public CheckItemsTask(){}
public CheckItemsTask(Integer customerId, String methodName,
CyclicBarrier cyclicBarrier, CheckResultVO checkResultVO){
this.customerId = customerId;
this.methodName = methodName;
this.cyclicBarrier = cyclicBarrier;
this.checkResultVO = checkResultVO;
}
synchronized public void run() {
try{
long startTime = System.currentTimeMillis();
excuteCheckTask(methodName, checkResultVO);
long endTime = System.currentTimeMillis();
LogUtils.logger().info("该校验方法 executeMethodName={} 的执行时间为 time={}", EXECUTE_PREFIX+methodName, endTime-startTime);
} finally {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
/**
* @param methodName
* @return
*/
private void excuteCheckTask(String methodName, CheckResultVO checkResultVO){
try {
String executeMethodName = EXECUTE_PREFIX + methodName;
if (StringUtils.equals(executeMethodName, "checkExistEffectiveContract") ||
StringUtils.equals(executeMethodName, "checkExistBusinessLeader")) {
Method m = c.getDeclaredMethod(executeMethodName, Integer.class, CheckResultVO.class);
m.invoke(settleOrderService, customerId, checkResultVO);
} else {
Method m = c.getDeclaredMethod(executeMethodName, Integer.class);
boolean flag = (boolean) m.invoke(settleOrderService, customerId);
String settleMethodName = SETTLE_PREFIX + methodName;
setCheckValue(settleMethodName, flag);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* @param settleMethodName
* @param isTrue
*/
private void setCheckValue(String settleMethodName, boolean isTrue) {
try {
Class c = checkResultVO.getClass();
Method m = c.getMethod(settleMethodName, Boolean.class);
m.invoke(checkResultVO, isTrue);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
用Future实现
List> results = Lists.newArrayList();
for (int i = 0; i < size; i++) {
results.add(threadPool.submit(new CheckItemsTaskS(
customerId, executeMethods[i], CheckResultVO)));
}
results.stream().forEach(r -> {
try {
r.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
public class CheckItemsTaskS implements Callable {
String EXECUTE_PREFIX = Constant.EXECUTE_METHOD_START_STR;
String SETTLE_PREFIX = Constant.SETTLE_METHOD_START_STR;
private CheckResultVO checkResultVO;
private String methodName;
private Integer customerId;
SettleOrderService settleOrderService = SpringUtils.getBean(SettleOrderService.class);
Class c = settleOrderService.getClass();
public CheckItemsTaskS(){}
public CheckItemsTaskS(Integer customerId, String methodName, CheckResultVO checkResultVO){
this.customerId = customerId;
this.methodName = methodName;
this.checkResultVO = checkResultVO;
}
@Override
public Object call() throws Exception {
long startTime = System.currentTimeMillis();
excuteCheckTask(methodName, checkResultVO);
long endTime = System.currentTimeMillis();
LogUtils.logger().info("该校验方法 executeMethodName={} 的执行时间为 time={}", EXECUTE_PREFIX+methodName, endTime-startTime);
return checkResultVO;
}
/**
* @param methodName
* @return
*/
private void excuteCheckTask(String methodName, CheckResultVO checkResultVO){
try {
String executeMethodName = EXECUTE_PREFIX + methodName;
if (StringUtils.equals(executeMethodName, "checkExistEffectiveContract") ||
StringUtils.equals(executeMethodName, "checkExistBusinessLeader")) {
Method m = c.getDeclaredMethod(executeMethodName, Integer.class, CheckResultVO.class);
m.invoke(settleOrderService, customerId, checkResultVO);
} else {
Method m = c.getDeclaredMethod(executeMethodName, Integer.class);
boolean flag = (boolean) m.invoke(settleOrderService, customerId);
String settleMethodName = SETTLE_PREFIX + methodName;
setCheckValue(settleMethodName, flag);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* @param settleMethodName
* @param isTrue
*/
private void setCheckValue(String settleMethodName, boolean isTrue) {
try {
Class c = checkResultVO.getClass();
Method m = c.getMethod(settleMethodName, Boolean.class);
m.invoke(checkResultVO, isTrue);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}