文章目录
异步线程
1)、继承 Thread
Threader01 thread = new Thread010;
thread, start();/启动线程
2)、实现 Runnable接口
RunabLe01 runabLe01 = new RunabLe010);
new Thread(runabLe01)start;
3)、实现 Callable接口+ Future Task(可以拿到返回结果,可以处理异常)
FutureTask<Integer) futureTask = new Future Task<>(new CaLLabLe01())
new Thread (future Task).start;
//阻塞等待整个线程执行完成,获取返回结果
Integer integer = futureTask. getO;
4)、线程池
给线程池直接提交任务。
区别
1、2不能得到返回值。3可以获取返回值
1、2、3都不能控制资源
4、可以控制资源,新能稳定
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
ExecutorService executorService = Executors.newFixedThreadPool(10);
线程回顾案例
/**
* @program: gulimall
* @description: 线程测试类
* @author: Mr.Lu
* @create: 2020-08-17 00:28
**/
public class ThreadTest {
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start......");
MyThread myThread = new MyThread();
myThread.start();
//-----------------------------------------------------
MyRunable myRunable = new MyRunable();
new Thread(myRunable).start();
new Thread(() -> {
System.out.println("内部Thread当前线程---" + Thread.currentThread().getId());
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("内部Runnable当前线程---" + Thread.currentThread().getId());
}
}).start();
//-----------------------------------------------------
/**
* 最大的好处,可以返回线程运行的结果
* 但是是堵塞线程,因为主线程一直要等待Callable运行结束接受值
*/
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
new Thread(futureTask).start();
//阻塞等待整个线程执行完成,获取返回值
Integer integer = futureTask.get();
System.out.println("MyCallable的执行结果"+integer);
/**
* 这样不好返回结果了
*/
new Thread(new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int i = 10 / 2;
System.out.println("内部类的----运行结果" + i);
return i;
}
})).start();
/**
* 如果想要拿到结果方式二,不用在建类
*/
FutureTask<Integer> futureTask1 = new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int i = 10 / 2;
System.out.println("MyRunable运行结果" + i);
return i;
}
});
new Thread(futureTask1).start();
Integer integer1 = futureTask1.get();
System.out.println("Callable内部类的执行结果"+integer);
System.out.println("main...end......");
}
//-----------------------自己定义类继承方式------------------------------
public static class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("MyThread运行结果" + i);
}
}
public static class MyRunable implements Runnable {
@Override
public void run() {
System.out.println("MyRunable当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("MyRunable运行结果" + i);
}
}
public static class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("MyRunable当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("MyRunable运行结果" + i);
return i;
}
}
}
运行结果
main...start......
MyThread当前线程==11
MyThread运行结果5
内部Thread当前线程---12
MyRunable当前线程==13
MyRunable运行结果5
内部Runnable当前线程---14
MyRunable当前线程==15
MyRunable运行结果5
MyCallable的执行结果5
内部类的----运行结果5
MyRunable运行结果5
Callable内部类的执行结果5
main...end......
线程池
给线程池提交任务
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("执行线程");
}
});
创建
使用Executor创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
常见的4种线程池
Executors.newCachedThreadPool
core是0,所以都可回收
- 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
Executors.newFixedThreadPool(值)
固定大小,core=max 都不可回收
- 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
Executors.newScheduledThreadPool(size)
做定时任务线程池
- 创建一个定长线程池,支持定时及周期性任务执行。
Executors.newSingleThreadExecutor
单线程的线程池,后台从队列获取任务,挨个执行
- 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务
原生线程池
/**
* 七大参数
* int corePoolSize,[5] 核心线程数[一直存在];线程池,创建好以后就准备就绪的线程数量,就等待来接受异步任务去执行(除非设置了{@code allowCoreThreadTimeOut})
* int maximumPoolSize, 最大线程数量;控制资源
* long keepAliveTime, 存活时间,如果当前的线程数量大于核心corePoolSize数量,
* 就释放空闲线程(maximumPoolSize-corePoolSize),只要线程空闲的时间大于指定的keepAliveTime
* TimeUnit unit, 时间单位
* BlockingQueue<Runnable> workQueue, 阻塞队列;如果任务有很多,就会将目前多的任务放入到队列中,只要有空闲线程,就去队列中去除新的任务继续执行
* ⚠️如果用 new LinkedBlockingDeque<>():默认是integer的最大值,会导致内存不够,所以要指定数量
* ThreadFactory threadFactory, 线程的创建工厂
* RejectedExecutionHandler handler 如果队列workQueue满了,按照指定的拒绝策略,拒绝执行任务
*
*/
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
200,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory() ,
new ThreadPoolExecutor.AbortPolicy());
/**
* 面试题:一个线程池 core7,max20,Queue50,100个并发进来怎么分配
* 7个会立即执行,50个会进入队列,在开13个进行执行,剩下30个使用拒绝策略
*/
工作流程、
- 线程池创建,准备好core数量的核心线程,准备接受任务
- 新的任务进来,用core准备好的空闲线程执行。
- core满了,就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
- 阻塞队列满了,就直接开新线程执行,最大只能开到max指定的数量
- max都执行好了。 Max-core数量空闲的线程会在 keepAlive Time指定的时间后自动销毀。最终保持到core大小
- 如果线程数开到了max的数量,还有新任务进来,就会使用 reject指定的拒绝策略进行处理
- 所有的线程创建都是由指定的 factory创建的。
Future可以获取到异步结果
CompletableFuture异步编排
统一解释:
不带Async的就和上一个线程用同一个线程来处理
带Async的将接下来处理是的内容 还是按照 异步线程,交给线程池,让线程池拿一个线程来处理
创建异步线程的四种方法
//不指定线程池
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 ThreadTest {
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start......");
//--------------------------------------------------------------
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
System.out.println("当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("runAsync运行结果" + i);
}, executor/*交给哪个线程池处理*/);
//--------------------------------------------------------------
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("supplyAsync运行结果" + i);
return i;/*带返回值,可以交给下面的回调方法处理,也可以直接取*/
}, executor/*交给哪个线程池处理*/);
//取值
Integer integer = integerCompletableFuture.get();
System.out.println("打印返回值" + integer);
//--------------------------------------------------------------
System.out.println("main...end......");
}
}
执行结果
main...start......
当前线程==11
runAsync运行结果5
当前线程==12
supplyAsync运行结果5
打印返回值5
main...end......
线程完成时回调感知(CompletableFuture)
//当线程运行成功后,回调什么
//不带Async的就和上一个线程用同一个线程来处理---可以得到线程执行结果,和得到异常信息,但是没办法修改结果
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)
//带Async的将接下来处理是的方式还是按照 异步线程,交给线程池,让线程池拿一个线程来处理
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)
案例
public class ThreadTest {
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start......");
//-------------------------线程回调-------------------------------------
CompletableFuture<Integer> futureComplete = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程==" + Thread.currentThread().getId());
int i = 10 / 0;
System.out.println("MyThread运行结果" + i);
return i;
}, executor).whenComplete((result, excption) -> {
//虽然能得到异常信息,但是没办法修改结果
System.out.println("异步任务完成了。。。结果是:" + result + ";异常是:" + excption);
}).exceptionally(throwable -> {
//感知异常,同时返回默认值
return 10;
});
//--------------------------------------------------------------
System.out.println("main...end......");
}
}
执行结果
main...start......
-------------------------线程回调-------------------------------------
当前线程==13
异步任务完成了。。。结果是:null;异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
main...end......
handel线程完成后的处理
//可以感知异常,并且可以对结果进行处理返回
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)
案例
public class ThreadTest {
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start......");
//--------------------------handel------------------------------------
CompletableFuture<Integer> futureHandel = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("MyThread运行结果" + i);
return i;
}, executor).handle((result, excption) -> {
System.out.println("异步任务完成了。。。结果是:" + result + ";异常是:" + excption);
if (result != null) {
return result * 2;
}
if (excption != null) {
return 0;
}
return 0;
});
//--------------------------------------------------------------
System.out.println("main...end......");
}
}
执行结果
main...start......
--------------------------handel------------------------------------
当前线程==14
MyThread运行结果5
异步任务完成了。。。结果是:5;异常是:null
main...end......
线程串行化
// A--CompletableFuture的异步任务执行结束了可以 |.thenRun| 接下来继续执行什么 B后续异步任务
//A-->B,⚠️不可以感知A的执行结果(不呢接收A的返回值,自己也无返回值)
public CompletableFuture<Void> thenRun (Runnable action)
public CompletableFuture<Void> thenRunAsync (Runnable action)
public CompletableFuture<Void> thenRunAsync (Runnable action,Executor executor)
// A--CompletableFuture的异步任务执行结束了可以 |.thenAccept| 接下来继续执行什么 B后续异步任务
//A-->B,⚠️可以感知A的执行结果(可以拿到A的返回值,自己无返回值)
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)
// A--B--C
//A把执行结果给B,B可以感知接收返回值,并且处理后自己在返回一个值给C(可以拿到A的值,自己也带返回值)
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 class ThreadTest {
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start......");
//--------------------------串行化------------------------------------
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("future1运行结果" + i);
return i;
}, executor).thenApply(future2 -> {
int i = future2 + 1;
System.out.println("thenApply运行结果" + i);
return i;
}).thenAccept(future3 -> {
int i = future3 + 1;
System.out.println("thenAccept运行结果" + i);
}).thenRun(()->{
System.out.println("thenRun运行结果:等我其他线程结束,我来做我自己的事情");
});
//--------------------------------------------------------------
System.out.println("main...end......");
}
}
执行结果
--------------------------串行化------------------------------------
main...start......
当前supplyAsync线程==11
future1运行结果5
当前thenApply线程==11
thenApply运行结果6
当前thenAccept线程==13
thenAccept运行结果7
当前thenRun线程==13
thenRun运行结果:等我其他线程结束,我来做我自己的事情
main...end......
两任务组合–都要完成
//CompletableFuture线程A.runAfterBoth(线程B,线程C)//将A,B组合在一起,运行完了,执行线程C
⚠️ //runAfterBoth组合两个线程,不能获取到组合线程的结果
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线程A.runAfterBoth(线程B,线程C)//将A,B组合在一起,运行完了,执行线程C
⚠️//线程C有两个参数,接受A,B任务执行成功的返回值
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)
//CompletableFuture线程A.runAfterBoth(线程B,线程C)//将A,B组合在一起,运行完了,执行线程C
⚠️//线程C有三个参数,接受A,B任务执行成功的返回值,并且自己做处理,返回一个值
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 class ThreadTest {
//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main...start......");
//--------------------------两任务组合------------------------------------
CompletableFuture<Integer> futureCombine = CompletableFuture.supplyAsync(() -> {
System.out.println("当前任务1线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1运行结果" + i);
return i;
}, executor).thenCombineAsync(CompletableFuture.supplyAsync(()->{
System.out.println("当前任务2线程==" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务2运行结果" + i);
return i;
}),(result, result2)->{
System.out.println("当前任务3线程==" + Thread.currentThread().getId());
int i = result + result2;
System.out.println("任务2运行结果" + i);
return i;
});
//--------------------------------------------------------------
System.out.println("main...end......");
}
}
执行结果
--------------------------两任务组合------------------------------------
main...start......
当前任务1线程==17
任务1运行结果5
当前任务2线程==16
任务2运行结果5
当前任务3线程==16
任务3运行结果10
main...end......
两任务组合–只要完成一个就执行C
//两个任务A B有一个执行完成,不需要获取 future的结果,处理任务C,也没有返值
⚠️ //runAfterEither组合两个线程,不能获取到组合线程的结果
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)
//两个任务A B有一个执行完成,获取它的返回值,处理任务C,没有新的返回值。
⚠️//线程C有一个参数,接受A,B任意一个任务执行成功的返回值
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)
//两个任务A B有一个执行完成,获取它的返回值,在任务C处理 并有新的返回值。
⚠️//线程C有一个参数,接受A,B任意一个任务执行成功的返回值,并且自己做处理,返回一个值
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 static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
//等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
allOf.get();//⚠️等待所有的结果完成
项目线程池配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @program: Initialize
* @description: 线程池配置
* @author: Mr.Lu
* @create: 2020-08-17 19:01
**/
@Configuration
public class MyThreadConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
return new ThreadPoolExecutor(
pool.getCoreSize(),
pool.getMaxiSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
}
让他变成可在yml配置的
/**
* @program: Initialize
* @description: 线程池的属性配置类
* @author: Mr.Lu
* @create: 2020-08-17 19:08
**/
@ConfigurationProperties(prefix = "thread")
@Component
@Data
public class ThreadPoolConfigProperties {
/**
* 核心线程数
*/
private Integer coreSize;
/**
* 最大线程数量
*/
private Integer maxiSize;
/**
* 存活时间
*/
private Integer keepAliveTime;
}
properties
# 核心线程数
thread.core-size=20
# 最大线程数量
thread.maxi-size=200
# 存活时间
thread.keep-alive-time=10
为了让配置的时候有提示请导入依赖,
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>