CyclicBarrier使用:
想象成一个场景:每一个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个没有准备好,大家都等待。
多个阻塞线程等待着一个barrier确定。
package t18;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UserCyclicBarrier {
static class Runner implements Runnable{
private String name;
private CyclicBarrier barrier;
public Runner(CyclicBarrier barrier,String name){
this.barrier = barrier;
this.name = name;
}
@Override
public void run() {
try {
System.out.println("好了,运动员" + name + "已经准备就绪了~");
barrier.await();//运动员进入阻塞等待
Thread.sleep(3000);
System.out.println(name + "gogogo!!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3);
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new Runner(barrier, "张三"));
executor.submit(new Runner(barrier, "李四"));
executor.submit(new Runner(barrier, "王五"));
executor.shutdown();
}
}
}
输出结果:
好了,运动员张三已经准备就绪了~
好了,运动员李四已经准备就绪了~
好了,运动员王五已经准备就绪了~
张三gogogo!!
王五gogogo!!
李四gogogo!!
CountDownLacth使用:
他常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作。一个线程等待多个操作完成。
package t18;
import java.util.concurrent.CountDownLatch;
public class UserCountDownLatch {
public static void main(String[] args) {
final CountDownLatch countDown = new CountDownLatch(2);
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
try {
System.out.println("进入线程t1" + "等待其他线程处理完成...");
countDown.await();
System.out.println("t1线程继续执行~");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
try {
System.out.println("t2线程进行初始化操作(3s)...");
Thread.sleep(3000);
System.out.println("t2线程初始化完成~");
countDown.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"t2");
Thread t3 = new Thread(new Runnable(){
@Override
public void run() {
try {
System.out.println("t3线程进行初始化操作(2s)...");
Thread.sleep(2000);
System.out.println("t3线程初始化完成~");
countDown.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}
输出结果:
t3线程进行初始化操作(2s)...
进入线程t1等待其他线程处理完成...
t2线程进行初始化操作(3s)...
t3线程初始化完成~
t2线程初始化完成~
t1线程继续执行~
Callable和Future的使用:
Future模式非常适合在处理很耗时很长的业务逻辑时使用,可以减小系统的响应时间,提高系统的吞吐率。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class UseFuture implements Callable<String> {
private String para;
public UseFuture(String para){
this.para = para;
}
/**
* 这里真是的业务逻辑,其执行可能个很慢
*/
@Override
public String call() throws Exception {
//模拟执行耗时
Thread.sleep(5000);
String result = this.para + "处理完成~";
return result;
}
//主控制函数
public static void main(String args[]) throws InterruptedException, ExecutionException{
String queryStr = "query";
//构造FutureTask,并且传入需要真正进行业务逻辑处理的类,该类一定事先Callable接口的类
FutureTask<String> futureTask1 = new FutureTask<>(new UseFuture(queryStr));
FutureTask<String> futureTask2 = new FutureTask<>(new UseFuture(queryStr));
//创建一个固定线程的线程池线程数为2
ExecutorService executor = Executors.newFixedThreadPool(2);
//这里日交任务future,则开启线程执行RealData的call()方法执行
Future f1 = executor.submit(futureTask1);
Future f2 = executor.submit(futureTask2);
System.out.println("请求完毕");
System.out.println(f1.get());
System.out.println(f2.get());
try {
System.out.println("处理实际的业务逻辑...");
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("数据:" + futureTask1.get());
System.out.println("数据:" + futureTask2.get());
executor.shutdown();
}
}
输出结果:
请求完毕
null
null
处理实际的业务逻辑...
数据:query处理完成~
数据:query处理完成~