大家好,我是烤鸭:
今天说一下 多线程的几种创建方式及使用。
1. Thread 和 Runnable
继承 Thread 类 和实现 Runnable 接口。
这种就不举例子了。
2.线程池
现在主要有5种线程池。
//缓存线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//固定大小线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
//单线程执行
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
//定时或延迟执行
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
//窃取线程池
ExecutorService workStealingPool = Executors.newWorkStealingPool();
其中 newWorkStealingPool 是jdk 1.8以后新出的,为了防止线程池启用过多,导致cpu占用过多导致的项目宕机。适用于执行多任务,且每个任务耗时时间较短。
其余4种方式都有可能会出现占用cpu过高导致的项目宕机的情况。
以 4核 16G的机器为例, Executors.newFixedThreadPool(10) 这种方式创建的线程池大小为10。
Executors.newWorkStealingPool() 创建线程池大小为4。一般来说,和核数相等。
即便不使用这种方式,也建议不要超过 核数 * 2。(具体看需求)
3. Future和CompletableFuture
Future 是 jdk1.5 以后出现的,用于异步多线程。
例子:
// 创建Future集合,用于存放完成的Future
List<Future<Long>> futureList = new ArrayList();
//多线程执行任务
for (int i = 0; i < 100; i++) {
Future<Long> testFuture= workStealingPool.submit(new Callable<Long>() {
@Override
public Long call() {
//模拟执行耗时任务
System.out.println("task 1 doing...");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
return 0L;
}
});
futureList.add(testFuture);
}
//遍历list,获取线程结果
for (Future<Long> taskResponseFuture: futureList) {
if(taskResponseFuture.get().equals(0L)){
//当前future执行完毕
}
}
这里注意一下,Future.get()是阻塞方法。如果需要多线程执行操作,在最后的时候执行get()方法。
类似上边的例子,可以把 多个 Future 放到list中,再循环get。
CompletableFuture 是 Future的实现类,关于异步多线程提供了更多的api,下面介绍几种常用的。
supplyAsync 异步执行,有返回值
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
//模拟执行耗时任务
System.out.println("task 1 doing...");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
//返回结果
return 0;
});
thenAccept 接收上一阶段的输出作为本阶段的输入。多线程(单个线程)的顺序执行。
completableFuture1.thenApply(new Function<Integer, Object>() {
@Override
public Object apply(Integer integer) {
//模拟执行耗时任务
System.out.println("task thenApply doing...");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
});
whenComplete 异步监听结果
completableFuture1.whenComplete(new BiConsumer<Integer,Throwable>() {
@Override
public void accept(Integer o, Throwable o2) {
if(o == 0L){
System.out.println("task complete...");
}else{
throw new RuntimeException();
}
}
});