- 线程的创建方式
-
继承Thread
package thread.ThreadCreate; public class ExtendThread { public static void main(String[] args) { System.out.println("main...start..."); Thread thread = new Thread01(); thread.start(); System.out.println("main...end..."); } public static class Thread01 extends Thread{ @Override public void run(){ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("执行结果:" + i); } } }
-
实现Runnable
package thread.ThreadCreate; public class ImplementRunnable { public static void main(String[] args) { System.out.println("main...start..."); Runnable runnable = new Runnable01(); new Thread(runnable).start(); System.out.println("main...end..."); } public static class Runnable01 implements Runnable{ @Override public void run(){ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("执行结果:" + i); } } }
-
实现Callable+通过FutureTask执行线程
package thread.ThreadCreate; import java.util.concurrent.*; public class ThreadPool { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("main...start..."); ExecutorService service = Executors.newFixedThreadPool(10); // 无返回值 service.execute(new Runnable01()); // 有返回值 Future<Integer> future = service.submit(new Callable01()); Integer result = future.get(); System.out.println("main...end..." + result); } public static class Runnable01 implements Runnable{ @Override public void run(){ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("执行结果:" + i); } } public static class Callable01 implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("执行结果:" + i); return i; } } }
- 线程池七大参数
- corePoolSize(核心线程数)
创建好以后就准备就绪的线程数量.除非设置了allowCoreThreadTimeOut,否则会一直存在 - maximumPoolSize(最大线程数量)
能够创建的最大线程数量,用以控制资源. - keepAliveTime(线程池中空闲线程等待工作的超时时间)
如果当前线程数大于核心线程数,并且线程空闲时间大于keepAliveTime,则会释放空闲线程,但会保证释放后的线程数大于等于核心线程数. - TimeUnit unit(时间单位)
即keepAliveTime的时间单位 - BlockingQueue workQueue(堵塞队列)
当任务很多时,没有更多的线程去执行,那么多的任务就会放在堵塞队列中,只要有线程空闲,就从堵塞队列中取出新的任务执行. - ThreadFactory(线程创建工厂)
- RejectedExecutionHandler handler(拒绝执行任务处理器)
如果堵塞队列满了,就按照指定的拒绝策略拒绝执行任务
- 线程池的执行顺序
- 线程池创建,准备core数量的核心线程,准备接收任务
- 当core满了,再进来的任务就会放入到堵塞队列中.空闲的核心线程会去堵塞队列中获取任务执行
- 如果堵塞队列也满了,则创建新线程执行,最大只能创建指定的maximumPoolSize数量.
- 如果堵塞队列满了,并且线程池也开到了最大线程数,那么就使用RejectedExecutionHandler拒绝执行任务
- 如果创建了多于核心线程数的线程,并且空闲,则在keepAliveTime时间后释放多余空闲的线程.
- 一个线程池,core:7,max:20,queue50,100个并发进行怎么执行
- 7个任务占用7个核心线程会立刻执行
- 50个任务放入堵塞队列中
- 再开13个线程执行任务
- 剩余的30个并发任务使用拒绝策略
- 常见的四种线程池
- newCachedThreadPool(可缓存线程池)
如果线程池长度超过处理需要,可灵活回收空闲线程(只要线程空闲,所有线程都可回收),如果线程不够用于执行任务,则创建新的线程去执行.
本质上是调用原生的ThreadPoolExecutor方法(核心线程数为0, 最大线程数为Integer.MAX_VALUE). - newFixedThreadPool(固定数量线程池)
核心线程数和最大线程数相等.所有线程都不可回收
本质上调用原生的ThreadPoolExecutor方法. - newScheduledThreadPool(定时任务线程池)
- newSingleThreadExecutor(单线程的线程池)
后台从队列中获取任务,挨个执行
本质上是调用原生的ThreadPoolExecutor方法(核心线程数和最大线程数都为1).
- 开发中为什么使用线程池
- 降低资源消耗
通过重复利用已经创建好的线程降低线程创建和销毁带来的损耗 - 提高响应速度
有的线程可能处于等待分配任务的状态,当任务来时无须创建新的线程就能执行 - 提高线程的可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销.无限的创建和销毁线程不仅消耗系统资源,还会降低系统的稳定性,使用线程池进行统一分配.
- CompletableFuture异步编排
-
CompletableFuture的使用
package thread.ThreadCreate; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CompletableFutureUse { // 创建一个大小为10的固定大小线程池, public static ExecutorService executor = Executors.newFixedThreadPool(10); public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("main...start..."); // runAsync没有返回值 CompletableFuture<Void> future = CompletableFuture.runAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 /2; System.out.println("运行结果:" + i); }, executor); // supplyAsync有返回结果 CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 /2; System.out.println("运行结果:" + i); return i; }, executor).whenComplete((res, exception)->{ // whenComplete可以处理正常和异常的计算结果,但是没有返回值 System.out.println("异步任务成功完成。。结果是:" + res + "异常是:" + exception); }).exceptionally(exception->{ // exceptionally,处理异常,返回一个异常情况下的默认值 System.out.println("异常是:" + exception); return 10; }); System.out.println("main...end..." + completableFuture.get()); } }
-
计算完成时的回调方法
- whenComplete: 处理正常和异常情况下的计算结果,但是没有返回值.执行当前任务的线程继续执行whenComplete的任务.
- whenCompleteAsync: 执行whenCompleteAsync的任务提交给线程池来执行,如果使用的是同一个线程池,也有可能被同一个线程执行.
- exceptionally: 处理异常情况,返回一个默认值
-
handle(异步任务执行完后的处理)
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("运行结果:" + i); return i; }, executor).handle((res, throwable)->{ if(res != null){ return res * 2; } if(throwable != null){ return 0; } return 0; });
-
线程串形化
-
thenRun: 不能获得上一步的执行结果,无返回值
CompletableFuture<Void> completableFuture2 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("运行结果:" + i); return i; }, executor).thenRun(()->{ System.out.println("任务2启动了"); });
-
thenRunAsync: 不能获得上一步的执行结果,无返回值.执行thenRunAsync的任务提交给线程池来执行
CompletableFuture<Void> completableFuture2 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("运行结果:" + i); return i; }, executor).thenRunAsync(()->{ System.out.println("任务2启动了"); },executor);
-
thenAcceptAsync: 能接受上一步结果,但是无返回值
CompletableFuture<Void> completableFuture3 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("运行结果:" + i); return i; }, executor).thenAcceptAsync((res)->{ System.out.println("任务2启动了"); System.out.println("上一个任务的返回结果为:" + res); },executor);
-
thenApplyAsync: 既能接受上一步的结果,也有返回值
CompletableFuture<Integer> completableFuture4 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("运行结果:" + i); return i; }, executor).thenApplyAsync((res)->{ System.out.println("任务2启动了"); System.out.println("上一个任务的返回结果为:" + res); return res * res; },executor); System.out.println("main...end..." + completableFuture4.get());
-
-
两任务组合-都要完成
-
thenCombine: 组合两个future,获取两个future的返回结果,并返回当前任务的返回值
CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("任务1结束"); return i; }, executor); CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 3 / 2; System.out.println("任务2结束"); return i; }, executor); CompletableFuture<String> task3 = task1.thenCombineAsync(task2,(t1, t2)->{ System.out.println("任务3开始...任务1和任务2的结果分别为:" + t1 + "=>" + t2); return "task3"; });
-
thenAcceptBoth: 组合两个future,获取两个future的返回结果,然后处理任务,没有返回值
System.out.println("测试两任务组合。。。"); CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("任务1结束"); return i; }, executor); CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 3 / 2; System.out.println("任务2结束"); return i; }, executor); task1.thenAcceptBothAsync(task2,(t1, t2)->{ System.out.println("任务3开始...任务1和任务2的结果分别为:" + t1 + "=>" + t2); });
-
runAfterBoth: 组合两个future,不需要获取future的结果,只需要两个future处理完任务后,处理该任务
CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 11 / 2; System.out.println("任务1结束"); return i; }, executor); CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(()->{ System.out.println("当前线程:" + Thread.currentThread().getId()); int i = 3 / 2; System.out.println("任务2结束"); return i; }, executor); task1.runAfterBothAsync(task2,()->{ System.out.println("任务3开始"); });
-
-
两任务组合-一个完成
- applyToEither: 两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
- acceptEither: 两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值
- runAfterEither: 两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值
-
多任务组合
-
allOf(所有任务都要执行成功)
CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(()->{ System.out.println("查询商品的图片信息"); return "hello.jpg"; }, executor); CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(()->{ System.out.println("查询商品的属性信息"); return "黑色+256G"; }, executor); CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(()->{ try { Thread.sleep(1000); System.out.println("查询商品的描述信息"); } catch (InterruptedException e) { e.printStackTrace(); } return "苹果13"; }, executor); CompletableFuture<Void> allof = CompletableFuture.allOf(futureImg, futureAttr, futureDesc); // 作用是等待所有结果完成,否则由于异步,可能先执行其他操作 allof.get();
-
anyOf(只要有一个任务执行成功即可)
代码与allOf类似
-