1.初始化线程的4 种方式
1.继承 Thread
package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MytestApplicationTests {
@Test
public void test() {
Thread1 thread1 = new Thread1();
thread1.run();
}
/**
* 继承Thread接口
*/
public class Thread1 extends Thread{
@Override
public void run() {
System.out.println("thread1运行开始");
try {
Thread.sleep(5000);//单位毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1运行结束");
}
}
}
2.实现 Runnable 接口
package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MytestApplicationTests {
@Test
public void test() {
Thread2 thread2 = new Thread2();
thread2.run();
}
/**
* 实现Runnable接口
*/
public class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("thread2运行开始");
try {
Thread.sleep(5000);//单位毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2运行结束");
}
}
}
3.实现 Callable 接口
FutureTask可以拿到返回结果,可以处理异常
futureTask.get()阻塞等待整个线程执行完成,获取返回结果
package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@SpringBootTest
public class MytestApplicationTests {
@Test
public void test() throws ExecutionException, InterruptedException {
Callable01 callable01 = new Callable01();
FutureTask<Integer> futureTask = new FutureTask<>(callable01);
Thread thread = new Thread(futureTask);
thread.start(); //启动线程
Integer integer = futureTask.get();//等待线程返回结果之前, 下面的代码不会执行
System.out.println(integer);
System.out.println("任务完成");
}
/**
* 实现Callable接口
*/
public class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("thread3运行开始");
try {
Thread.sleep(5000);//单位毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread3运行结束");
return 10;
}
}
}
4.线程池ExecutorService
package com.atguigu.gulimall.mytest;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.*;
@SpringBootTest
public class MytestApplicationTests {
@Test
public void test() throws ExecutionException, InterruptedException {
Callable01 callable01 = new Callable01();
ExecutorService executorService = Executors.newFixedThreadPool(10);
FutureTask<Integer> futureTask = (FutureTask<Integer>)executorService.submit(callable01);
System.out.println("等待结果");
System.out.println(futureTask.get());
System.out.println("任务完成");
}
/**
* 实现Callable接口
*/
public class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("thread3运行开始");
try {
Thread.sleep(5000);//单位毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread3运行结束");
return 10;
}
}
}
2.线程池的7大参数
线程池工作流程图
-
corePoolSize(必需):核心线程数。默认情况下,核心线程会一直存活,但是当将
allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。 -
maximumPoolSize(必需):线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。
-
keepAliveTime(必需):线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
-
unit(必需):指定 keepAliveTime参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。
-
workQueue(必需):任务队列。通过线程池的 execute() 方法提交的 Runnable对象将存储在该参数中。其采用阻塞队列实现。
-
threadFactory(可选):线程工厂。用于指定为线程池创建新线程的方式。
-
handler(可选):拒绝策略。当达到最大线程数时需要执行的饱和策略。
一个线程池 core 7; max 20 ,queue:50,100 并发进来怎么分配的?
先有 7 个能直接得到执行,接下来 50 个进入队列排队,在多开 13 个继续执行。现在 70 个 被安排上了。剩下 30 个默认拒绝策略。
3.常见的4 种线程池
-
newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若 无可回收,则新建线程。
-
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
-
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
-
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
4.CompletableFuture 异步编排
1.创建异步对象
CompletableFuture 提供了四个静态方法来创建一个异步操作。
1、runAsync都是没有返回结果的,supplyAsync都是可以获取返回结果的
2、可以传入自定义的线程池,否则就用默认的线程池;
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
//异步任务1
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("当前线程1:" + Thread.currentThread().getId());
int i = 10 / 2;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("运行结果1:" + i);
}, executor);
//异步任务2
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程2:" + Thread.currentThread().getId());
int i = 10 / 2;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("运行结果2:" + i);
return i;
}, executor);
Integer res2 = (Integer) future2.get();
System.out.println("res2="+res2);
}
}
2.计算完成时回调方法
- whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
- whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行whenComplete 的任务。 whenCompleteAsync:是执行把 whenCompleteAsync这个任务继续提交给线程池 来进行执行。 - 方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程
执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
1.在 supplyAsync、runAsync执行完毕后还想做其他任务就可以使用链式调用whenComplete(是指当前任务的线程执行继续执行)、whenCompleteAsync(是重新提交到线程池进行执行),这两个可以接收到成功值或者异常信息,只能作为监听成功或失败。
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "ok";
}, executor).whenComplete((res,exception)->{
System.out.println("结果是:"+res+"异常是:"+exception);
});
String res = future.get();
System.out.println("线程返回结果:"+res);
}
}
2.还可以链式调用exceptionally,可以获取到异常信息并且可以修改最终值.
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
int i = 10/0; //模拟异常
return "ok";
}, executor).whenComplete((res,exception)->{
System.out.println("结果是:"+res+"异常是:"+exception);
}).exceptionally((exception)->{
return "not ok";
});
String res = future.get();
System.out.println("线程返回结果:"+res);
}
}
3.handle 方法
handle方法可以接受两个参数(成功值,异常信息),返回一个参数(可以修改最终返回值),相当于方法执行后的处理
package com.atguigu.gulimall.mytest.test;
import io.swagger.models.auth.In;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//int i = 10/0; //模拟异常
return "ok";
}, executor).handle((res, exception) -> {
if (exception==null){
System.out.println("结果是:" + res);
return res;
}else{
System.out.println("异常是:" + exception);
return "not ok";
}
});
String res = future.get();
System.out.println("线程返回结果:"+res);
}
}
5.线程串行化方法
提示: 链式调用方法后不加Async是指当前任务的线程执行继续执行,加上Async是重新提交到线程池进行执行
1.thenRun、thenRunAsync
要上面的任务执行完毕后才开始执行此方法的后续操作,无返回结果。
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
System.out.println("one");
return "ok";
},executor).thenRunAsync(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行后续操作。。。");
},executor);
}
}
2.thenAccept、thenAcceptAsync
有一个入参(消费处理结果),接收处理结果进行后续操作,无返回结果。
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
System.out.println("one");
return "ok";
}, executor).thenAcceptAsync((res)->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收到结果:"+res+"执行后续操作。。。");
},executor);
}
}
3.thenApply、thenApplyAsync
接收返回结果,并进行后续操作,并返回当前任务的返回值
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "ok";
}, executor).thenApplyAsync((res)->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("接收到结果:"+res+"执行后续操作。。。");
return "ok666";
},executor);
String res = future.get();
System.out.println("线程返回结果:"+res);
}
}
4.两任务组合 - 都要完成
两个任务必须都完成,触发该任务。
1.thenCombine、thenCombineAsync:组合两个futre的返回结果,并且返回当前任务的返回值
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
return 10;
}, executor);
CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2执行完毕");
return 20;
}, executor);
CompletableFuture<Integer> combineAsync = supplyAsync1.thenCombineAsync(supplyAsync2, (res1, res2) -> {
System.out.println("结合任务1和任务2的结果计算出任务3,并返回");
return res1+res2;
}, executor);
Integer res = combineAsync.get();
System.out.println("结果:"+res);
}
}
2.thenAcceptBoth、thenAcceptBothAsync:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有返回值。
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
return 10;
}, executor);
CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2执行完毕");
return 20;
}, executor);
CompletableFuture<Void> acceptBothAsync = supplyAsync1.thenAcceptBothAsync(supplyAsync2, (res1, res2) -> {
System.out.println("结合任务1和任务2的结果执行任务3,没有返回值!");
System.out.println("res1+res2="+(res1+res2));
}, executor);
}
}
3.runAfterBoth、thenAfterBothAsync:组合两个futre,不需要返回结果,只需要处理两个Future后执行该任务。
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
return 10;
}, executor);
CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2执行完毕");
return 20;
}, executor);
CompletableFuture<Void> afterBothAsync = supplyAsync1.runAfterBothAsync(supplyAsync2, () -> {
System.out.println("任务1和任务2执行完执行任务3.没有返回值!");
}, executor);
}
}
5.两任务组合 - 一个完成
1.applyToEitherAsync、applyToEither: 两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
return 10;
}, executor);
CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2执行完毕");
return 20;
}, executor);
supplyAsync1.applyToEitherAsync(supplyAsync2,(res)->{
System.out.println("res="+res);
System.out.println("只要有一个完成就接收值,处理并返回值!");
return 3;
},executor);
}
}
2.acceptEitherAsync、acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
supplyAsync1.acceptEitherAsync(supplyAsync2,(res)->{
System.out.println("只要有一个完成就接收值,处理不能返回值!");
},executor);
3.runAfterEitherAsync、runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返回值。
supplyAsync1.runAfterEitherAsync(supplyAsync2,()->{
System.out.println("只要有一个完成不接受值,处直接理不能返回值!");
},executor);
6.多任务组合
1.allOf:等待所有任务完成,没有返回值
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
return 10;
}, executor);
CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务2执行完毕");
return 20;
}, executor);
CompletableFuture<Integer> supplyAsync3 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务3执行完毕");
return 30;
}, executor);
CompletableFuture<Void> all = CompletableFuture.allOf(supplyAsync1, supplyAsync2, supplyAsync3);
System.out.println("ok1");
all.get(); //阻塞,等待所有任务完成才执行后续代码
System.out.println("ok2");
}
}
2.anyOf:只要有一个任务完成, 可以有返回值
package com.atguigu.gulimall.mytest.test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class threadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
return 10;
}, executor);
CompletableFuture<Integer> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务2执行完毕");
return 20;
}, executor);
CompletableFuture<Integer> supplyAsync3 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务3执行完毕");
return 30;
}, executor);
CompletableFuture<Object> all = CompletableFuture.anyOf(supplyAsync1, supplyAsync2, supplyAsync3);
System.out.println("ok1");
Integer res = (Integer) all.get(); //阻塞,等待有一个任务完成才执行后续代码
System.out.println("res="+res);
System.out.println("ok2");
}
}