一、异步
1、初始化线程的四种方式
1.1、继承Thread
public class ThreadTest {
public static void main(String[] args) {
new Thread01().start();
}
public static class Thread01 extends Thread {
@Override
public void run() {
System.err.println("start......Thread01...");
}
}
}
1.2、实现Runnable接口
public class ThreadTest {
public static void main(String[] args) {
new Thread(new Runnable01()).start();
}
public static class Runnable01 implements Runnable {
@Override
public void run() {
System.err.println("start........Runnable01.");
}
}
}
1.3、实现Callable + FutureTask(可以获得返回值,可以处理异常 )
public class ThreadTest {
public static void main(String[] args) {
FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
new Thread(futureTask).start();
//阻塞等待
Integer integer = futureTask.get();
System.err.println(integer);
}
public static class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
return i;
}
}
}
1.4、线程池
public class ThreadTest {
static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
service.execute(new Runnable01());
}
public static class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
return i;
}
}
}
区别:
1、2 不能得到返回值,3可以得到返回值
1、2、3 都不能控制资源
4 可以控制资源,性能稳定
2、线程池详解
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
七大参数:
- corePoolSize: [5] 核心线程数;线程池,创建好以后就准备就绪的线程数量,就等待来就收异步任务去执行
5个 Thread thread=new Thread(); thread.start(); - maximumPoolSize:[200] 最大线程数;控制资源
- keepAliveTime: 存活时间。如果当前的线程数量大于核心数量 释放空闲的线程数(maximumPoolSize- corePoolSize)。只要线程空闲大于指定的keepAliveTime
- TimeUnit:时间单位
- BlockingQueue workQueue: 阻塞对列。如果任务有很多,就会将目前多的任务放到队列里面。 只要有线程空闲,就回去队列里面取出新的任务去执行**
- threadFactory: 线程创建工厂
- RejectedExecutionHandler handler:如果队列满了,按照我们指定的拒绝策略拒绝执行任务
public ThreadPoolExecutor(5,
200,
10,
TimeUnit.SECONDS,
new LinkBlockingQueue<>(100000),
Executors.DefaultThreadFactory,
ThreadPoolExecutor.AbortPolicy())
执行顺序
线程池创建, 准备好core数量的核心线程,准备接受任务
core 满了 , 就将再进来的任务放到阻塞队列中, 空闲的core就会自己去阻塞队列中获取任务执行阻塞队列满,就直接开新线程去执行,最大只能开到max指定的数量max满了就用RejectedExecutionHandler拒接任务`max都执行完成,有很多空闲,在指定的实践keepAliveTime以后,释放max-core这些线程new LinkedBlockingQueue() 默认为Integer最大值 , 可能造成系统内存不足
如果队列满 所使用的的 拒绝策略:
DiscardOldestPolicy : 放弃 最老的 任务
DiscardPolicy : 丢弃任务 , 不跑异常
AbortPolicy: 直接丢弃任务 , 抛异常 (默认)
CallerRunsPolicy : 以同步的方式执行 , 直接调用 run 方法
问题:一个线程池,core=7 max=20 queue=50 100个线程如何分配
7个线程直接运行 , 50 个进入队列 13 个 创建新的线程, 30个靠拒绝策略
如果不想抛弃还可以使用CallerRunsPolicy以同步的方式执行 , 直接调用 run 方法
3、常见的4种线程池
1、CachedThreadPool 自动扩展的 core是0,所有都可回收
2、FixedThreadPool 固定大小的 core=max 都不可回收
3、ScheduledThreadPool 定时任务的线程池
4、SingleThreadExecutor 单个线程的线程池 后台从队列获取任务按个执行
为何使用线程池
- 降低资源的消耗
通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗 - 提高响应速度
因为线程她中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行 - 提高线程的可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使用程池进行统—分配
二、CompletableFuture 异步编排
1、创建异步对象
Future 可以获取异步结果
//无返回值
public static CompletableFuture<Void> runAsync(Runnable runnable) //
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) // 指定线程池
//有返回值
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
测试启动
public class CompletableFutureTest {
static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.err.println("main...........start..........");
//---------------runAsync------------无返回值------------
// CompletableFuture.runAsync(() -> {
// System.err.println("当前线程:" + Thread.currentThread().getId());
// int i = 10 / 2;
// System.err.println("运行结果:" + Thread.currentThread().getId() + i);
// }, service);
//---------------supplyAsync---------有返回值---------------
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.err.println("运行结果:" + i);
return i;
}, service);
Integer result = supplyAsync.get();
System.err.println(result);
System.err.println("main...........end..........");
}
}
2、计算完成时回调方法
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync( BiConsumer<? super T, ? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor) // 能感知到异常,但是不能返回异常结果
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn) // 感知异常 返回默认值
- whenComplete 可以处理正常和异常的计算结果 ,exceptionally 处理异常情况
- whenComplete , whenCompleteAsync 的区别
whenComplete 执行当前任务的的线程继续执行whenComplete的任务 whenCompleteAsync 是执行把whenCompleteAsync 这个任务继续提交给线程池来执行 方法不以 Async 结尾,意味着Action使用相同的线程执行 , 而Async 可能会使用其他线程执行(如果使用相同的线程池,也肯能被同一个线程选中执行)
public class CompletableFutureTest {
static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.err.println("main...........start..........");
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 0;
System.err.println("运行结果:" + i);
return i;
}, service).whenComplete((result, exception) -> {
//虽然得到异步信息,但是没法返回数据
System.err.println("异步任务成功完成....结果是:" + result + "异常是:" + exception);
}).exceptionally((throwable)->{
//可以感知异常,同时返回默认值
return 10;
});
Integer result = supplyAsync.get();
System.err.println(result);
System.err.println("main...........end..........");
}
}
3、handle 执行完后的处理
方法:
public <U> CompletableFuture<U> handle( BiFunction<? super T, Throwable, ? extends U> fn)
public <U> CompletableFuture<U> handleAsync( BiFunction<? super T, Throwable, ? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
使用:
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("运行结果:" + i);
return i;
}, service).handle((result,throwable)->{
//方法执行完后的处理
if(result!=null){
return result*2;
}
if(throwable!=null){
return 10;
}
return 0;
});
4、线程串行化方法
方法:
// 获取上一个任务的返回结果,并返回当前任务的返回结果
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
// 消费处理结果
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)
// 只要上面的任务执行完成, 就开始执行thenRun,只是处理任务后,执行thenRun的后续操作
public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)
使用:
CompletableFuture<Void> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("运行结果:" + i);
return i;
}, service).thenRunAsync(()->{
System.err.println("任务二启动了.....");
},service);
System.err.println("main...........end..........");
thenRun : 不能获取上一部的执行结果 无返回值
CompletableFuture<Void> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("运行结果:" + i);
return i;
}, service).thenAcceptAsync((res)->{
System.err.println(res);
System.err.println("任务二启动了.....");
},service);
System.err.println("main...........end..........");
thenAcceptAsync: 能接受到上一步的结果 ,无返回值
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.err.println("当前线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("运行结果:" + i);
return i;
}, service).thenApplyAsync((res)->{
System.err.println(res);
System.err.println("任务二启动了.....");
return res;
},service);
Integer integer = supplyAsync.get();
System.err.println("main...........end.........."+integer);
thenApplyAsync 能接受上一步的结果,有返回值 对应Async默认是异步执行的,同之前。
5、两任务组合-都要完成
方法:
// 拿到前面的任务结果, 返回自己的 结果
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync( CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor)
public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor)
// 不能获取 future 结果 , 两个任务完成后触发
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action, Executor executor)
列子:
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务1线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("任务1结果:" + i);
return i;
}, service);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务2线程:" + Thread.currentThread().getId());
System.err.println("任务2结束");
return "Hello";
}, service);
CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
return f1 + ":" + f2 + "--> haha";
}, service);
System.err.println(future.get());
System.err.println("main...........end..........");
结论: thenCombine : 组合两个future,获取两个future的返回结果,并返回当前任务的返回值
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务1线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("任务1结果:" + i);
return i;
}, service);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务2线程:" + Thread.currentThread().getId());
System.err.println("任务2结束");
return "Hello";
}, service);
future01.thenAcceptBothAsync(future02,(f1,f2)->{
System.err.println("任务3线程开始:" + Thread.currentThread().getId());
System.err.println("f1====>"+f1+",f3===>"+f2);
},service);
System.err.println("main...........end..........");
结论: thenAcceptBoth : 组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值。
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务1线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("任务1结果:" + i);
return i;
}, service);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务2线程:" + Thread.currentThread().getId());
System.err.println("任务2结束");
return "Hello";
}, service);
future01.runAfterBothAsync(future02,()->{
System.err.println("任务3线程:" + Thread.currentThread().getId());
System.err.println("任务3结果:");
},service);
System.err.println("main...........end..........");
结论: runAfterBoth : 组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务。
6、两任务组合-一个完成
方法:
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor)
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync( CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor)
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)
例子: 当两个任务中,任意一个future任务完成的时候,执行任务。
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务1线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("任务1结果:" + i);
return i;
}, service);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务2线程:" + Thread.currentThread().getId());
try {
Thread.sleep(3000);
System.err.println("任务2结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello";
}, service);
CompletableFuture<String> apply = future01.applyToEitherAsync(future02, res -> res.toString() + "哈哈", service);
System.err.println(apply.get());
System.err.println("main...........end..........");
结论: applyToEither : 两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务1线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("任务1结果:" + i);
return i;
}, service);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务2线程:" + Thread.currentThread().getId());
try {
Thread.sleep(3000);
System.err.println("任务2结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello";
}, service);
//acceptEitherAsync没有返回结果
future01.acceptEitherAsync(future02,(res)->{
System.err.println("任务3开始..........之前的结果:"+res);
},service);
结论: acceptEither : 两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务1线程:" + Thread.currentThread().getId());
int i = 100 / 5;
System.err.println("任务1结果:" + i);
return i;
}, service);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.err.println("任务2线程:" + Thread.currentThread().getId());
try {
Thread.sleep(3000);
System.err.println("任务2结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello";
}, service);
future01.runAfterEitherAsync(future02,()->{
System.err.println("任务3开始..........之前的结果");
},service);
结论: runAfterither : 两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值。
7、多任务组合
方法:
// 全部完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
// 完成一个
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
例子: 获取一个商品的图片介绍和sku
CompletableFuture<Object> futureImg = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("商品图片");
return "hello.jpg";
}, service);
CompletableFuture<Object> futureAttr = CompletableFuture.supplyAsync(() -> {
System.err.println("商品查询");
return "黑色+256G";
}, service);
CompletableFuture<Object> futureDesc = CompletableFuture.supplyAsync(() -> {
System.err.println("商品介绍");
return "华为";
}, service);
CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
//阻塞等待
allOf.get();
System.err.println(futureImg.get()+"----->"+futureAttr.get()+"......"+futureDesc.get());
System.err.println("main...........end..........");
总结: allOf : 等待所有任务完成
CompletableFuture<Object> futureImg = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("商品图片");
return "hello.jpg";
}, service);
CompletableFuture<Object> futureAttr = CompletableFuture.supplyAsync(() -> {
System.err.println("商品查询");
return "黑色+256G";
}, service);
CompletableFuture<Object> futureDesc = CompletableFuture.supplyAsync(() -> {
System.err.println("商品介绍");
return "华为";
}, service);
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
Object o = anyOf.get();
System.err.println("结果:"+o);
System.err.println("main...........end..........");
总结: anyOf : 只有一个任务完成
8、配置类
import com.xiesn.springboot.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置
*
**/
@Configuration
public class ThreadPoolConfig {
// 核心线程池大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}
任务
package com.xiesn.springboot.component;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* <p>
* 任务工厂
* </p>
*/
@Component
@Slf4j
public class TaskFactory {
/**
* 模拟5秒的异步任务
*/
@Async
public Future<Boolean> asyncTask1() throws InterruptedException {
doTask("asyncTask1", 5);
return new AsyncResult<>(Boolean.TRUE);
}
/**
* 模拟2秒的异步任务
*/
@Async
public Future<Boolean> asyncTask2() throws InterruptedException {
doTask("asyncTask2", 2);
return new AsyncResult<>(Boolean.TRUE);
}
/**
* 模拟3秒的异步任务
*/
@Async
public Future<Boolean> asyncTask3() throws InterruptedException {
doTask("asyncTask3", 3);
return new AsyncResult<>(Boolean.TRUE);
}
/**
* 模拟5秒的同步任务
*/
@SneakyThrows
public void task1() {
doTask("task1", 5);
}
/**
* 模拟2秒的同步任务
*/
@SneakyThrows
public void task2() {
doTask("task2", 2);
}
/**
* 模拟3秒的同步任务
*/
@SneakyThrows
public void task3() {
doTask("task3", 3);
}
@SneakyThrows
private void doTask(String taskName, Integer time) {
log.info("{}开始执行..........,当前线程名称【{}】", taskName, Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(time);
log.info("{}执行成功,当前线程名称【{}】", taskName, Thread.currentThread().getName());
}
}
使用:
package com.xiesn.springboot.thread;
import cn.hutool.core.date.DateUtil;
import com.xiesn.springboot.component.TaskFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.*;
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class AsyncTest {
@Autowired
TaskFactory taskFactory;
@Autowired
ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
ScheduledExecutorService scheduledExecutorService;
/**
* 测试异步任务
*/
@Test
public void asyncTaskTest() throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
Future<Boolean> asyncTask1 = taskFactory.asyncTask1();
Future<Boolean> asyncTask2 = taskFactory.asyncTask2();
Future<Boolean> asyncTask3 = taskFactory.asyncTask3();
// 调用 get() 阻塞主线程
asyncTask1.get();
asyncTask2.get();
asyncTask3.get();
long end = System.currentTimeMillis();
log.info("异步任务全部执行结束,总耗时:{} 毫秒" , (end - start));
}
/**
* 测试同步任务
*/
@Test
public void taskTest() {
long start = System.currentTimeMillis();
taskFactory.task1();
taskFactory.task2();
taskFactory.task3();
long end = System.currentTimeMillis();
log.info("同步任务全部执行结束,总耗时:{} 毫秒" , (end - start));
}
/**
* 测试线程池
*/
@SneakyThrows
@Test
public void threadPoolTest() {
final LocalDateTime start = LocalDateTime.now();
System.err.println("main...........start..........");
//---------------runAsync------------带返回值------------
CompletableFuture<String> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
taskFactory.task1();
return "task1";
}, threadPoolTaskExecutor);
System.out.println("task1:");
//---------------runAsync------------带返回值------------
CompletableFuture<String> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
taskFactory.task2();
return "task2";
}, threadPoolTaskExecutor);
System.out.println("结果task2:");
//---------------runAsync------------带返回值------------
CompletableFuture<String> supplyAsync3 = CompletableFuture.supplyAsync(() -> {
taskFactory.task3();
return "task3";
}, threadPoolTaskExecutor);
System.out.println("结果task3:");
//等待所有任务完成 //阻塞方法get()
CompletableFuture.allOf(supplyAsync1, supplyAsync2, supplyAsync3).get();
final LocalDateTime end = LocalDateTime.now();
System.out.println(Duration.between(start, end).toMillis());
}
/**
* 测试
*/
@Test
public void scheduledTest() {
System.err.println("start....."+ DateUtil.now());
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
log.info("异步任务全部执行结束,总耗时:{} 毫秒" , DateUtil.now());
}
}, 1000, 1 * 60 * 1000, TimeUnit.MILLISECONDS);
//nitialDelay – 延迟第一次执行的时间
//period – 连续执行之间的时间段
//unit – initialDelay 和 period 参数的时间单位
//阻塞等待防止结束.....
while (true){
}
}
}