代码:
https://gitee.com/hsjjsh123/multi-thread.git
上结论:
demo为先,上代码:
一、Futrue:
package com.hsj.future;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @author denny.zhang
* @author HeShengjin 2356899074@qq.com
* @ClassName: FutureDemo
* @Description: Future多线程并发任务结果归集
* @date 2016年11月4日 下午1:50:32
*/
public class FutureDemo {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
//开启多线程
ExecutorService exs = Executors.newFixedThreadPool(10);
try {
//结果集
List<Integer> list = new ArrayList<Integer>();
List<Future<Integer>> futureList = new ArrayList<Future<Integer>>();
//1.高速提交10个任务,每个任务返回一个Future入list
for (int i = 0; i < 10; i++) {
futureList.add(exs.submit(new CallableTask(i + 1)));
}
Long getResultStart = System.currentTimeMillis();
System.out.println("结果归集开始时间=" + new Date());
//2.结果归集,用迭代器遍历futureList,高速轮询(模拟实现了并发),任务完成就移除
while (futureList.size() > 0) {
Iterator<Future<Integer>> iterable = futureList.iterator();
//遍历一遍
while (iterable.hasNext()) {
Future<Integer> future = iterable.next();
//如果任务完成取结果,否则判断下一个任务是否完成
// if (future.isDone() && !future.isCancelled()){//非阻塞
//获取结果
Integer i = future.get();//阻塞
System.out.println("任务i=" + i + "获取完成,移出任务队列!" + new Date());
list.add(i);
//任务完成移除任务
iterable.remove();
// }else{
// Thread.sleep(1);//避免CPU高速运转,这里休息1毫秒,CPU纳秒级别
// }
}
}
System.out.println("list=" + list);
System.out.println("总耗时=" + (System.currentTimeMillis() - start) + ",取结果归集耗时=" + (System.currentTimeMillis() - getResultStart));
} catch (Exception e) {
e.printStackTrace();
} finally {
exs.shutdown();
}
}
}
package com.hsj.future;
import java.util.Date;
import java.util.concurrent.Callable;
public class CallableTask implements Callable<Integer> {
Integer i;
public CallableTask(Integer i) {
super();
this.i = i;
}
@Override
public Integer call() throws Exception {
if (i == 1) {
Thread.sleep(3000);//任务1耗时3秒
} else if (i == 5) {
Thread.sleep(5000);//任务5耗时5秒
} else {
Thread.sleep(1000);//其它任务耗时1秒
}
System.out.println("task线程:" + Thread.currentThread().getName() + "任务i=" + i + ",完成!"+ new Date());
return i;
}
}
二、FutureTask:
package com.hsj.futuretask;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
*
* @ClassName:FutureTaskDemo
* @Description:FutureTask实现多线程并发执行任务并取结果归集
* 有点儿类似于Promise方式
* @author diandian.zhang
* @author HeShengjin 2356899074@qq.com
* @date 2017年6月16日上午10:36:05
*/
public class FutureTaskDemo {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
//开启多线程
ExecutorService exs = Executors.newFixedThreadPool(10);
try {
//结果集
List<Integer> list = new ArrayList<Integer>();
List<FutureTask<Integer>> futureList = new ArrayList<FutureTask<Integer>>();
//启动线程池,10个任务固定线程数为5
for(int i=0;i<10;i++){
FutureTask<Integer> futureTask = new FutureTask<Integer>(new CallableTask(i+1));
//提交任务,添加返回,Runnable特性
exs.submit(futureTask);
//Future特性
futureList.add(futureTask);
}
Long getResultStart = System.currentTimeMillis();
System.out.println("结果归集开始时间="+new Date());
//结果归集
while(futureList.size()>0){
Iterator<FutureTask<Integer>> iterable = futureList.iterator();
//遍历一遍
while(iterable.hasNext()){
Future<Integer> future = iterable.next();
// if (future.isDone()&& !future.isCancelled()) {//非阻塞
//Future特性
Integer i = future.get();//阻塞
System.out.println("任务i=" + i + "获取完成,移出任务队列!" + new Date());
list.add(i);
//任务完成移除任务
iterable.remove();
// }else {
// //避免CPU高速轮循,可以休息一下。
// Thread.sleep(1);
// }
}
}
System.out.println("list="+list);
System.out.println("总耗时="+(System.currentTimeMillis()-start)+",取结果归集耗时="+(System.currentTimeMillis()-getResultStart));
} catch (Exception e) {
e.printStackTrace();
} finally {
exs.shutdown();
}
}
}
package com.hsj.futuretask;
import java.util.Date;
import java.util.concurrent.Callable;
/**
* @Description 回调方法
* @author denny
* @author HeShengjin 2356899074@qq.com
* @date 2018/8/17 下午3:16
*/
public class CallableTask implements Callable<Integer> {
Integer i;
public CallableTask(Integer i) {
super();
this.i = i;
}
@Override
public Integer call() throws Exception {
if (i == 1) {
Thread.sleep(3000);//任务1耗时3秒
} else if (i == 5) {
Thread.sleep(5000);//任务5耗时5秒
} else {
Thread.sleep(1000);//其它任务耗时1秒
}
System.out.println("task线程:" + Thread.currentThread().getName() + "任务i=" + i + ",完成!"+ new Date());
return i;
}
}
三、CompletionService:
package com.hsj.completionservice;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
*
* @ClassName: CompletionServiceDemo
* @Description: CompletionService多线程并发任务结果归集
* @author denny.zhang
* @author HeShengjin 2356899074@qq.com
* @date 2016年11月4日 下午1:50:32
*
*/
public class CompletionServiceDemo{
public static void main(String[] args) {
Long start = System.currentTimeMillis();
//开启多线程
ExecutorService exs = Executors.newFixedThreadPool(10);
try {
int taskCount = 10;
//结果集
List<Integer> list = new ArrayList<Integer>();
//1.定义CompletionService
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(exs);
List<Future<Integer>> futureList = new ArrayList<Future<Integer>>();
//2.添加任务
for(int i=0;i<taskCount;i++){
futureList.add(completionService.submit(new Task(i+1)));
}
//==================结果归集===================
//方法1:future是提交时返回的,遍历queue则按照[任务提交顺序],获取结果
for (Future<Integer> future : futureList) {
System.out.println("====================");
Integer result = future.get();//线程在这里阻塞等待该任务执行完毕,按照
System.out.println("任务result="+result+"获取到结果!"+new Date());
list.add(result);
}
// //方法2.使用内部阻塞队列的take()
// for(int i=0;i<taskCount;i++){
// Integer result = completionService.take().get();//采用completionService.take(),内部维护阻塞队列,[任务先完成的先获取到]
// System.out.println("任务i=="+result+"完成!"+new Date());
// list.add(result);
// }
System.out.println("list="+list);
System.out.println("总耗时="+(System.currentTimeMillis()-start));
} catch (Exception e) {
e.printStackTrace();
} finally {
exs.shutdown();//关闭线程池
}
}
}
package com.hsj.completionservice;
import java.util.concurrent.Callable;
public class Task implements Callable<Integer> {
Integer i;
public Task(Integer i) {
super();
this.i=i;
}
@Override
public Integer call() throws Exception {
if(i==5){
Thread.sleep(5000);
}else{
Thread.sleep(1000);
}
System.out.println("线程:"+Thread.currentThread().getName()+"任务i="+i+",执行完成!");
return i;
}
}
四、CompletableFuture:
package com.hsj.completablefuture;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @ClassName:CompletableFutureDemo
* @Description:多线程并发任务,取结果归集
* @author diandian.zhang
* @author HeShengjin 2356899074@qq.com
* @date 2017年6月14日下午12:44:01
*/
public class CompletableFutureDemo {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
//结果集
List<String> list = new ArrayList<String>();
//定长10线程池
ExecutorService exs = Executors.newFixedThreadPool(10);
List<CompletableFuture<String>> futureList = new ArrayList<>();
//任务
final List<Integer> taskList = new ArrayList(){{
add(2); add(1); add(3); add(6); add(4); add(5); add(8); add(9); add(7); add(10);
}};
try {
// 方式一:全流式处理转换成CompletableFuture[]+组装成一个无返回值CompletableFuture,join等待执行完毕。返回结果whenComplete获取
CompletableFuture[] cfHaveBack = taskList
.stream()
.map(
object-> CompletableFuture.supplyAsync(()->calc(object), exs)
.thenApply(integer->Integer.toString(integer))//中间的转换
//如需获取任务完成先后顺序,此处代码即可
.whenComplete((v, e) -> {
System.out.println("任务"+v+"完成!result="+v+",异常 e="+e+","+new Date());
list.add(v);
})
).toArray(CompletableFuture[]::new);
//等待总任务完成,但是封装后无返回值,必须自己whenComplete()获取
CompletableFuture.allOf(cfHaveBack).join();
System.out.println("任务完成,结果list="+list+";耗时="+(System.currentTimeMillis()-start));
//华丽丽的分割线
System.out.println("///");
//方式二:全流式处理转换成CompletableFuture[]+组装成一个无返回值CompletableFuture,join等待执行完毕。无返回值。
CompletableFuture[] cfNoBack = taskList
.stream()
.map(
object-> CompletableFuture.runAsync(
()->calcV2(taskList,object),
exs)
).toArray(CompletableFuture[]::new);
//等待总任务完成,但是封装后无返回值,必须自己whenComplete()获取
CompletableFuture.allOf(cfNoBack).join();
System.out.println("任务完成,结果taskList="+taskList+";耗时="+(System.currentTimeMillis()-start));
} catch (Exception e) {
e.printStackTrace();
}finally {
exs.shutdown();
}
}
/**
* @Description:有返回值
* @author HeShengjin 2356899074@qq.com
* @date 2021/11/18 10:21
*/
public static Integer calc(Integer i){
try {
if(i==1){
//任务1耗时3秒
Thread.sleep(3000);
}else if(i==5){
//任务5耗时5秒
Thread.sleep(5000);
}else{
//其它任务耗时1秒
Thread.sleep(1000);
}
System.out.println("task线程:"+Thread.currentThread().getName()+"任务i="+i+",完成!+"+new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
return i;
}
/**
* @Description:没有返回值
* @author HeShengjin 2356899074@qq.com
* @date 2021/11/18 10:21
*/
public static void calcV2(List<Integer> taskList,Integer i){
try {
if(i==1){
//任务1耗时3秒
Thread.sleep(3000);
}else if(i==5){
//任务5耗时5秒
Thread.sleep(5000);
}else{
//其它任务耗时1秒
Thread.sleep(1000);
}
//自己的业务逻辑
System.out.println("task线程:"+Thread.currentThread().getName()+"任务i="+i+",完成!+"+new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
感谢:
多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture