一、继承Thread类
public class ThreadTest {
public static void main(String[] args) throws Exception {
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 = 10 / 2;
System.out.println("运行结果:" + i);
}
}
}
二、实现Runnable接口
public class ThreadTest {
public static void main(String[] args) throws Exception {
Runable01 runable01 = new Runable01();
new Thread(runable01).start();
}
public static class Runable01 implements Runnable {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
}
}
}
三、实现Callable接口
public class ThreadTest {
public static void main(String[] args) throws Exception {
FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
public static class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}
}
}
四、线程池方式
4.1 Executors工具类
public class ThreadTest {
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
service.execute(new Runable01());
Future<Integer> submit = service.submit(new Callable01());
submit.get();
}
public static class Runable01 implements Runnable {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 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 = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}
}
}
4.1.1 常见的四种线程池
- newCachedThreadPool
参数:核心线程数是0,最大线程数为Integer最大值
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无法回收,则新建线程。 - newFixedThreadPool(int nThreads)
参数:核心线程数是nThreads,最大线程数也是nThreads,存活时间是0L一直存活
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 - newScheduledThreadPool(int corePoolSize)
参数:
创建一个定长线程池,支持定时及周期性执行任务。 - newSingleThreadExecutor
参数:核心线程数是1,最大线程数也是1,存活时间是0L一直存活,队列是无界队列
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
4.2 ThreadPoolExecutor原生方式
4.2.1 线程池七大参数
(1)corePoolSize
默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。
(2)maximumPoolSize
当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。
(3)keepAliveTime
当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。
(4)unit - {keepAliveTime}参数的时间单位。
(5)workQueue - 一个阻塞队列,用来存储等待执行的任务。
(6)threadFactory - 执行器创建新线程时要使用的工厂。
(7)handler - 表示当拒绝处理任务时的策略。
4.2.2 执行任务逻辑
(1)判断核心线程数是否已满,核心线程数大小和corePoolSize参数有关,未满则创建线程执行任务.
(2)若核心线程池已满,判断队列是否满,队列是否满和workQueue参数有关,若未满则加入队列中。
(3)若队列已满,判断线程池是否已满,线程池是否已满和maximumPoolSize参数有关,若未满创建线程执行任务。
(4)若线程池已满,则采用拒绝策略处理无法执执行的任务,拒绝策略和handler参数有关。
4.2.3 拒绝策略
(1)CallerRunsPolicy:由调用线程处理该任务
(2)AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常
(3)DiscardPolicy:丢弃任务,但是不抛出异常。
(4)DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务。
五、CompletableFuture异步编排
5.1 应用场景
复杂业务逻辑查询,需要异步且相互之间有关系,某些任务需要其他任务返回结果(类似于vue调用ajax请求,需要某些ajax请求时,then)
5.2 基本使用
5.2.1 简单体验
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* 创建异步对象
* runAsync:无返回值
* supplyAsync:有返回值
*/
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
}, executor);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor);
System.out.println("future2.get() = " + future2.get());
}
}
5.2.2 whenComplete 方法完成后的感知(但是无法修改返回数据)
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* whenComplete
* 方法完成后的感知
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 0;
System.out.println("运行结果:" + i);
return i;
}, executor).whenComplete((res,exception) -> {
//虽然能得到异常信息,但是没法修改返回数据
System.out.println("异步任务成功完成了...结果是:" + res + "异常是:" + exception);
}).exceptionally(throwable -> {
//可以感知异常,同时返回默认值
return 10;
});
Integer integer = future.get();
System.out.println("integer = " + integer);
}
}
5.2.3 handle 方法执行完后的处理
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* handle
* 方法执行完后的处理
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).handle((result,thr) -> {
if (result != null) {
return result * 2;
}
if (thr != null) {
System.out.println("异步任务成功完成了...结果是:" + result + "异常是:" + thr);
return 0;
}
return 0;
});
System.out.println("future.get() = " + future.get());
}
}
5.2.4 线程串行化
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* 线程串行化
* 1、thenRunAsync:不能获取上一步的执行结果
* 2、thenAcceptAsync:能接受上一步结果,但是无返回值
* 3、thenApplyAsync:能接受上一步结果,有返回值
*
*/
CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenRunAsync(() -> {
System.out.println("任务2启动了...");
}, executor);
CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenAcceptAsync(res -> {
System.out.println("任务2启动了..." + res);
}, executor);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenApplyAsync(res -> {
System.out.println("任务2启动了..." + res);
return "Hello" + res;
}, executor);
System.out.println("main......end....." + future.get());
}
}
5.2 两任务组合(都要完成)
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* 两任务组合:都要完成
* runAfterBoth:获取不到前面两个任务的结果
* thenAcceptBothAsync:能获取到前面两个任务的结果,没有返回值
* thenCombineAsync:能获取到前面两个任务的结果,有返回值
*/
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
System.out.println("任务2结束:");
return "Hello";
}, executor);
// future01.runAfterBothAsync(future02, () -> {
// System.out.println("任务3开始。。。");
// } ,executor);
// future01.thenAcceptBothAsync(future02, (f1, f2) -> {
// System.out.println("任务3开始。。。之前的结果:" + f1 + "-->" + f2);
// } , executor);
CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
return f1 + " : " + f2 + " -> Hah..";
}, executor);
System.out.println("future.get() = " + future.get());
}
}
5.3 两任务组合(一个完成)
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* 两任务组合:一个完成
* runAfterEitherAsync:任意一个任务完成后,获取不到它的结果,没有返回值
* acceptEither:任意一个任务完成后,能获取到它的结果,没有返回值
* applyToEither:任意一个任务完成后,能获取到它的结果,有返回值
*/
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
System.out.println("任务2结束:");
return "Hello";
}, executor);
// future01.runAfterEitherAsync(future02, () -> {
// System.out.println("任务3开始。。。");
// }, executor);
// future01.acceptEitherAsync(future02, (res) -> {
// System.out.println("任务3开始。。。" + res);
// } , executor);
CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
System.out.println("任务3开始。。。获取到的res:" + res);
return "当前任务的res:" + res + "...hello...";
}, executor);
System.out.println("future.get() = " + future.get());
}
}
5.4 多任务组合
public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws Exception {
/**
* 多任务组合
* allOf:等待所有任务完成
* anyOf:只要有一个任务完成
*/
CompletableFuture<String> futureImage = 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(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询商品介绍");
return "华为";
}, executor);
// CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImage, futureAttr, futureDesc);
// allOf.get();// 等待所有结果完成
// System.out.println("获取结果:" + futureImage.get() + " : " + futureAttr.get() + " : " + futureDesc.get());
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImage, futureAttr, futureDesc);
anyOf.get();// 等待任意一个结果完成
System.out.println("获取结果:" + anyOf.get());
System.out.println("main...end...");
// 打印疑问:因为使用线程池,所以所有任务都会执行完成
}
}
5.5 实际多任务组合业务代码
说明:因为future01的结果其他的线程需要使用,所以使用CompletableFuture.supplyAsync(),future02需要使用future01的结果所以使用thenAcceptAsync,future03同理。因为future04的结果其他的线程不需要使用,所以使用CompletableFuture.runAsync()。CompletableFuture.allOf(future01,future02,future03,future04).get();等待所有的线程任务完成,主线程继续执行。
CompletableFuture<SkuInfoEntity> future01 =CompletableFuture.supplyAsync(() ->{
//业务逻辑res=xxx;
return res;
}, executor);
CompletableFuture<Void> future02 = future01.thenAcceptAsync((res) -> {
// 业务逻辑res.getXxx()
}, executor);
CompletableFuture<Void> future03 = future01.thenAcceptAsync((res) -> {
// 业务逻辑res.getXxx()
}, executor);
CompletableFuture<Void> future04 = CompletableFuture.runAsync(() -> {
// 业务逻辑
}, executor);
//等到所有任务都完成
CompletableFuture.allOf(future01,future02,future03,future04).get();