代码顺序
3.1 CountDownLatch/Phaser
3.2CompletableFuture
3.3 Fork/Join
3.1 CountDownLatch/Phaser
/**
* @author lmc
* @Email huyang@126.com
* @date 2018年10月10日
*
* 3.1 CountDownLatch/Phaser
*
*/
public class CountDownTask {
private static final int CORE_POOL_SIZE = 4;
private static final int MAX_POOL_SIZE = 12;
private static final long KEEP_ALIVE_TIME = 5L;
private final static int QUEUE_SIZE = 1600;
//ConcurrentLinkedQueue 非阻塞队列
//LinkedBlockingQueue 阻塞队列 ,阻塞队列常用于生产者和消费者的场景
//这笔订单可能还需要查,用户信息,折扣信息,商家信息,菜品信息等,用同步的方式调用
protected final static ExecutorService THREAD_POOL = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
KEEP_ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue<>(QUEUE_SIZE));
public static void main(String[] args) throws InterruptedException {
CountDownLatch countdown = new CountDownLatch(5);
THREAD_POOL.execute(()->{
System.out.println("当前任务Customer,线程名字为:"+Thread.currentThread().getName());
// orderInfo.setCustomerInfo(new CustomerInfo());
countdown.countDown();
});
THREAD_POOL.execute(()->{
System.out.println("当前任务Discount,线程名字为:"+Thread.currentThread().getName());
countdown.countDown();
});
THREAD_POOL.execute(()->{
System.out.println("当前任务Food,线程名字为:"+Thread.currentThread().getName());
countdown.countDown();
});
THREAD_POOL.execute(()->{
System.out.println("当前任务Tenant,线程名字为:"+Thread.currentThread().getName());
countdown.countDown();
});
THREAD_POOL.execute(()->{
System.out.println("当前任务OtherInfo,线程名字为:"+Thread.currentThread().getName());
countdown.countDown();
});
countdown.await(1,TimeUnit.SECONDS);
System.out.println("主线程: "+Thread.currentThread().getName());
/* 建立一个线程池(具体配置根据具体业务,具体机器配置),进行并发的执行我们的任务(生成用户信息,菜品信息等),
最后利用await方法阻塞等待结果成功返回。await()方法可以阻塞至超时或者计数器减至0,其他线程当完成自己目标的时候可以减少1,
利用这个机制我们可以将其用来做并发。
*/
// THREAD_POOL.shutdownNow();
//countDownLatch.countDown(),很明显我们的业务代码显然不应该关心这一部分逻辑,
//并且在开发的过程中万一写漏了,那我们的await方法将只会被各种异常唤醒。
}
}
3.2CompletableFuture
/**
* @author lmc
* @Email huyang@126.com
* @date 2018年10月10日
*
* 3.2 CompletableFuture
*
*/
public class CompletableFutureParallel {
private static final int CORE_POOL_SIZE = 4;
private static final int MAX_POOL_SIZE = 12;
private static final long KEEP_ALIVE_TIME = 5L;
private final static int QUEUE_SIZE = 1600;
//countDownLatch.countDown()与业务无关,每个线程都要执行,所以引出了CompletableFuture
//在JDK1.8中提供了一个类CompletableFuture,它是一个多功能的非阻塞的Future。
//我们将每个任务的计算完成的结果都用CompletableFuture来表示,利用CompletableFuture.
//allOf汇聚成一个大的CompletableFuture,那么利用get()方法就可以阻塞。
private final static ExecutorService THREAD_POOL = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(QUEUE_SIZE));
/**
* @param args
* @throws TimeoutException
* @throws ExecutionException
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
// TODO Auto-generated method stub
List<CompletableFuture> futures = new ArrayList<>();
futures.add(CompletableFuture.runAsync(()->{
System.out.println("当前任务Customer,线程名字为:" + Thread.currentThread().getName());
// orderInfo.setCustomerInfo(new CustomerInfo());
},THREAD_POOL));
futures.add(CompletableFuture.runAsync(() -> {
System.out.println("当前任务Discount,线程名字为:" + Thread.currentThread().getName());
//orderInfo.setDiscountInfo(new DiscountInfo());
}, THREAD_POOL));
futures.add( CompletableFuture.runAsync(() -> {
System.out.println("当前任务Food,线程名字为:" + Thread.currentThread().getName());
// orderInfo.setFoodListInfo(new FoodListInfo());
}, THREAD_POOL));
futures.add(CompletableFuture.runAsync(() -> {
System.out.println("当前任务Other,线程名字为:" + Thread.currentThread().getName());
// orderInfo.setOtherInfo(new OtherInfo());
}, THREAD_POOL));
CompletableFuture<?> allDoneFuture = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[futures.size()]));
allDoneFuture.get(10,TimeUnit.SECONDS);
System.out.println("主线程 : "+Thread.currentThread().getName());
}
}
3.3 Fork/Join
/**
* @author lmc
* @Email huyang@126.com
* @date 2018年10月11日
*
* 3.3 Fork/Join
*/
/*我们上面用CompletableFuture完成了我们对多组任务并行执行,但是其依然是依赖我们的线程池,在我们的线程池中使用的是阻塞队列,
* 也就是当我们某个线程执行完任务的时候需要通过这个阻塞队列进行,
* 那么肯定会发生竞争,所以在JDK1.7中提供了ForkJoinTask和ForkJoinPool。
* Fork/Join 框架就是必要情况下。将一个大任务,进行拆分fork成若干个小任务,再将每个小任务运行结棍join汇总
* */
public class ForkJoinPoolTask extends RecursiveTask{
@Override
protected ForkJoinPoolTask compute() {
System.out.println("执行"+ this.getClass().getSimpleName() + "线程名字为:" + Thread.currentThread().getName());
// 定义其他五种并行TasK
CustomerTask customerTask = new CustomerTask();
TenantTask tenantTask = new TenantTask();
DiscountTask discountTask = new DiscountTask();
FoodTask foodTask = new FoodTask();
OtherTask otherTask = new OtherTask();
invokeAll(customerTask, tenantTask, discountTask, foodTask, otherTask);
// OrderInfo orderInfo = new OrderInfo(customerTask.join(), tenantTask.join(), discountTask.join(), foodTask.join(), otherTask.join());
return null;
}
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors() -1 );
System.out.println(forkJoinPool.invoke(new ForkJoinPoolTask()));
}
}
class CustomerTask extends RecursiveTask{
@Override
protected CustomerTask compute() {
System.out.println("执行"+ this.getClass().getSimpleName() + "线程名字为:" + Thread.currentThread().getName());
return new CustomerTask();
}
}
class TenantTask extends RecursiveTask{
@Override
protected TenantTask compute() {
System.out.println("执行"+ this.getClass().getSimpleName() + "线程名字为:" + Thread.currentThread().getName());
return new TenantTask();
}
}
class DiscountTask extends RecursiveTask{
@Override
protected DiscountTask compute() {
System.out.println("执行"+ this.getClass().getSimpleName() + "线程名字为:" + Thread.currentThread().getName());
return new DiscountTask();
}
}
class FoodTask extends RecursiveTask{
@Override
protected FoodTask compute() {
System.out.println("执行"+ this.getClass().getSimpleName() + "线程名字为:" + Thread.currentThread().getName());
return new FoodTask();
}
}
class OtherTask extends RecursiveTask{
@Override
protected OtherTask compute() {
System.out.println("执行"+ this.getClass().getSimpleName() + "线程名字为:" + Thread.currentThread().getName());
return new OtherTask();
}
/* 我们定义一个OrderTask并且定义五个获取信息的任务,在compute中分别fork执行这五个任务,
最后在将这五个任务的结果通过Join获得,最后完成我们的并行化的需求。*/
}
详情参考如下,理解得非常好 多谢分享