多线程 线程池和异步编排
创建线程的三种方法
继承Thread类
使用时直接new 该实现类然后执行start方法便可以运行线程.
public void testSearchService() throws ExecutionException, InterruptedException {
new ThreadTest().start();
}
private static class ThreadTest extends Thread {
@Override
public void run() {
System.out.println("开始执行线程.");
int i = 200 / 10;
System.out.println(i);
System.out.println("线程执行结束.");
}
}
实现Runable接口
实现Runnable接口并实例化线程类 并将实现Runnable接口的实例对象实例化线程类的构造方法中,之后执行start方法便可以运行线程
public void testSearchService() throws ExecutionException, InterruptedException {
new Thread(new RunnableTest()).start();
}
private static class RunnableTest implements Runnable {
@Override
public void run() {
System.out.println("开始执行线程.");
int i = 200 / 10;
System.out.println(i);
System.out.println("线程执行结束.");
}
}
实现Callable<T>并实现FutureTask获取返回结果
首先实现Runnable接口 范型参数表示返回值类型
private static class CallableTest implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("开始执行线程.");
int i = 200 / 10;
System.out.println(i);
System.out.println("线程执行结束.");
return i;
}
}
然后实例化FutureTask,并在实例化FuterTask时传入Callable实例化对象, FetureTask的范型参数依旧是返回值类型. 之后实例化线程类并将FetureTask对象传入到线程类构造方法中, 之后执行start方法便可以执行线程, 执行feture.get()可以获取返回值, 如果一直获取不到返回值则会阻塞.
FutureTask<Integer> futureTask = new FutureTask<>(new CallableTest());
new Thread(futureTask).start();
Integer integer = futureTask.get();
System.out.println(integer);
总结
前两种创建线程无法获取返回值而第三种方法可以和获取返回值
三种方法都无法控制系统资源, 如果线程创建的太多则会导致系统资源耗尽, 这时候就需要线程池了.
线程池
创建线程池需要七个参数
int corePoolSize: 核心线程数, 当创建线程池是一并创建该数目的线程数
int maximumPoolSize: 最大线程数
long keepAliveTime: 空闲时间, 当线程空闲时间到达该数则会被释放, 释放到核心线程数目则不会被释放
TimeUnit unit: 空闲线程时间单位
BlockingQueue
ArrayBlockingQueue: 基于数组的有界存储队列
DelayQueue: 无边界存储队列
LinkedBlockingDeque: 基于链表的存储队列
LinkedTransferQueue: 基于链表且无界的存储队列
PriorityBlockingQuene: 具有优先级的无界阻塞队列;
ThreadFactory threadFactory 创建线程工厂类
RejectedExecutionHandler handler 线程拒绝策略 当线程池中的任务在执行且空闲任务队列已满 则会根据线程拒绝策略处理该任务
DiscardOldestPolicy: 丢弃最早执行任务 执行当前人物
AbortPolicy: 直接抛出异常
CallerRunsPolicy: 调用run方法来执行当前任务
DiscardPolicy: 直接丢弃最旧任务
private static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,
20,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new CallerRunsPolicy());
异步编排
CompletableFuture创建异步任务时分为runAsync()代表没有返回值supplyAsync()代表有返回值
当发生异常时会调用whenComplete语句块中的内容 但是不能返回结果
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("线程开始执行");
int i = 200 / 0;
System.out.println("线程执行完毕");
return i;
}).whenComplete((result , e) -> {
System.out.println(result);
System.out.println(e);
}).
如果想要设置返回结果那就得调用exceptionally语句块中的内容 处理异常并设置返回
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("线程开始执行");
int i = 200 / 0;
System.out.println("线程执行完毕");
return i;
}).exceptionally((e) -> {
System.out.println(e);
return 10;
});
根据是否发生异常来分别处理不同的业务可以调用handle语句块如果参数1不为空那么代表没异常 可以正常获取到上一步返回内容, 如果参数2不为空则表示执行出现了异常.
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("线程开始执行");
int i = 200 / 10;
System.out.println("线程执行完毕");
return i;
}).handle((result, exception) -> {
if (result != null) {
return result * 100;
}
if (exception != null) {
return 0;
}
return 0;
});
线程串行化
将线程任务以串行的方式进行执行
thenApplyAsync: 获取上一次的执行结果并返回结果值
thenAcceptAsync: 获取上一次返回结果不用返回值
thenRunAsync: 执行下一个任务
CompletableFuture<Void> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("线程开始执行");
int i = 200 / 10;
System.out.println("线程执行完毕");
return i;
}).thenApplyAsync((result) -> {
System.out.println(result);
return 2000;
}, threadPool).thenAcceptAsync((result) -> {
System.out.println(result);
}, threadPool).thenRunAsync(() -> {
System.out.println("任务2启动了");
});
组合两个任务
// 不获取前两次执行结果 也没有返回内容
completableFuture01.runAfterBothAsync(completableFuture02, () -> {
System.out.println("任务3开始执行");
System.out.println("任务3结束");
}, threadPool);
// 获取前两次执行结果 有返回内容
completableFuture01.thenAcceptBothAsync(completableFuture02, (result1, result2)-> {
System.out.println("任务3开始执行");
System.out.println("result1:" + result1);
System.out.println("result2:" + result2);
System.out.println("任务3结束");
}, threadPool);
//
// // 获取前两次执行结果 并返回内容
completableFuture01.thenCombineAsync(completableFuture02, (result1, result2) -> {
System.out.println("任务3开始执行");
System.out.println("result1:" + result1);
System.out.println("result2:" + result2);
System.out.println("任务3结束");
return result1 + result2;
}, threadPool);
组合两个任务, 一个任务完成即可立即执行第三个任务
两个任务返回值必须相同
// 无返回值且 且没有获取任务返回结果
completableFuture01.runAfterEitherAsync(completableFuture02, () -> {
System.out.println("任务3开始");
}, threadPool);
// 有返回值且 且可以获取任务返回结果
completableFuture01.applyToEitherAsync(completableFuture02, (result) -> {
System.out.println("任务3开始");
return 5500;
}, threadPool);
// 无返回值且 且可以获取任务返回结果
completableFuture01.acceptEitherAsync(completableFuture02, (result) -> {
System.out.println("任务3开始");
}, threadPool);
多任务组合
全部任务完成之后再将结果返回
allOf在所有方法执行完毕才会将结果进行返回
CompletableFuture<String> imgFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("获取商品图片");
return "lyra.png";
}, threadPool);
CompletableFuture<String> nameFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("获取商品名称");
return "lyra";
}, threadPool);
CompletableFuture<Double> priceFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("获取商品价格");
return 700.00;
}, threadPool);
CompletableFuture<Void> allCompletableFuture = CompletableFuture.allOf(imgFuture, nameFuture, priceFuture);
System.out.println(imgFuture.get());
System.out.println(nameFuture.get());
System.out.println(priceFuture.get());
任意任务完成立即返回
anyOf只要其中一个任务完成直接将结果进行返回
CompletableFuture<String> imgFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("获取商品图片");
return "lyra.png";
}, threadPool);
CompletableFuture<String> nameFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("获取商品名称");
return "lyra";
}, threadPool);
CompletableFuture<Double> priceFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("获取商品价格");
return 700.00;
}, threadPool);
CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(imgFuture, nameFuture, priceFuture);
System.out.println(objectCompletableFuture.get());
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律