Executor 接口关系
Callable:类似于Runnable,但是可以有返回值
Future:存储将来执行的结果。Callable被执行完之后的结果,被封装到Future里面。
Future 示例:
/**
* 认识Callable,对Runnable进行了扩展
* 对Callable的调用,可以有返回值
*/
package com.mashibing.juc.c_026_01_ThreadPool;
import java.util.concurrent.*;
public class T03_Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> c = new Callable() {
@Override
public String call() throws Exception {
return "Hello Callable";
}
};
ExecutorService service = Executors.newCachedThreadPool();
Future<String> future = service.submit(c); //异步
System.out.println(future.get());//阻塞
service.shutdown();
}
}
FutureTask:更加灵活,是Runnable和Future的结合,既是一个Runnable,又可以存结果
FutureTask示例:
/**
* 认识FutureTask
*/
package com.mashibing.juc.c_026_01_ThreadPool;
import java.util.concurrent.*;
public class T06_00_Future {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Integer> task = new FutureTask<>(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return 1000;
}); //new Callable () { Integer call();}
new Thread(task).start();
System.out.println(task.get()); //阻塞
}
}
CompletableFuture
可以用来管理多个Future的结果,对各种各样的结果进行组合处理。你可以去查查它的API~
提供了很多非常好用的接口,十分友好!
示例:假设你能够提供一个服务,这个服务查询各大电商网站同一类产品的价格并汇总展示,你用CompletableFuture开启三个线程来完成这个任务
package com.mashibing.juc.c_026_01_ThreadPool;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class T06_01_CompletableFuture {
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start, end;
/*start = System.currentTimeMillis();
priceOfTM();
priceOfTB();
priceOfJD();
end = System.currentTimeMillis();
System.out.println("use serial method call! " + (end - start));*/
start = System.currentTimeMillis();
CompletableFuture<Double> futureTM = CompletableFuture.supplyAsync(() -> priceOfTM());
CompletableFuture<Double> futureTB = CompletableFuture.supplyAsync(() -> priceOfTB());
CompletableFuture<Double> futureJD = CompletableFuture.supplyAsync(() -> priceOfJD());
CompletableFuture.allOf(futureTM, futureTB, futureJD).join(); // 提供对于一堆任务的管理:这三个任务全部完成之后,才能继续向下运行
// CompletableFuture.anyOf(futureTM, futureTB, futureJD).join(); // 任意一个任务完成,就能继续向下运行
CompletableFuture.supplyAsync(() -> priceOfTM())
.thenApply(String::valueOf)
.thenApply(str -> "price " + str)
.thenAccept(System.out::println);
end = System.currentTimeMillis();
System.out.println("use completable future! " + (end - start));
try {
System.in.read();//因为里面全是异步,所以需要阻塞一下,才能正常的等待它们输出,不然主线程先结束了。。
} catch (IOException e) {
e.printStackTrace();
}
}
private static double priceOfTM() {
delay();
return 1.00;
}
private static double priceOfTB() {
delay();
return 2.00;
}
private static double priceOfJD() {
delay();
return 3.00;
}
/*private static double priceOfAmazon() {
delay();
throw new RuntimeException("product not exist!");
}*/
private static void delay() {
int time = new Random().nextInt(500);
try {
TimeUnit.MILLISECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("After random %s sleep!\n", time);
}
}
线程池
ThreadPoolExecutor:我们通常所说的线程池
ForkJoinPoll:先将任务分解,最后再汇总
如何自定义一个线程池
阿里《Java开发手册》建议自定义线程池,所以我们先来看看如何自定义一个线程池。
线程池
维护两个集合:
- 线程集合
- 任务集合
用的是HashSet
定义一个自定义线程池,最多有7个参数,这个面试经常被使劲问
package com.mashibing.juc.c_026_01_ThreadPool;
import java.io.IOException;
import java.util.concurrent.*;
public class T05_00_HelloThreadPool {
static class Task implements Runnable {
private int i;
public Task(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Task " + i);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return "Task{" +
"i=" + i +
'}';
}
}
public static void main(String[] args) {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4,
60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(4),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
for (int i = 0; i < 8; i++) {
tpe.execute(new Task(i));
}
System.out.println(tpe.getQueue());
tpe.execute(new Task(100));
System.out.println(tpe.getQueue());
tpe.shutdown();
}
}