优缺点:
代码示例:
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class CreateThreadTest {
public static void main(String[] args) {
// 1、继承Thread
new Thread(new Thread01()).start();
// 2、实现Runnable
new Thread(new Rannable01()).start();
// 3、实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
FutureTask<String> stringFutureTask = new FutureTask<>(new Callable01());
new Thread(stringFutureTask).start();
try {
log.info("结果:{}",stringFutureTask.get());//阻塞式等待
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 4、线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.submit(()->log.info("方式4..."));//submit可以获取结果,execute无法获取结果
executorService.shutdown();//关闭
}
}
@Slf4j
class Thread01 extends Thread{
@Override
public void run() {
log.info("方式1...");
}
}
@Slf4j
class Rannable01 implements Runnable{
@Override
public void run() {
log.info("方式2...");
}
}
@Slf4j
class Callable01 implements Callable<String>{
@Override
public String call() throws Exception {
log.info("方式3...");
return "Callable01";
}
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
int corePoolSize
,核心线程数【只要线程池不销毁(设置allowCoreThreadTimeOut属性),就一直存在】;线程池创建好之后准备就绪的线程数,等待接收异步亲求去执行;int maximumPoolSize
,最大线程数,可用于控制资源long keepAliveTime
,存活时间,当前线程数量大于指定的核心线程数量,只要存活时间达到该值,就会被释放。(maximumPoolSize-corePoolSize)TimeUnit unit
,时间单位BlockingQueue workQueue
,阻塞队列,如果任务很多,多余的任务会被放在队列中ThreadFactory threadFactory
,创建线程的工厂RejectedExecutionHandler handler
如果队列满了,按照我们指定的拒绝策略执行任务工作顺序
corePoolSize
)的核心线程,以接收任务workQueue
)中,当有空闲核心线程,就会去阻塞队列中获取任务maximumPoolSize
指定的数量maximumPoolSize
个线程,就用拒绝策略拒绝任务corePoolSize
),多出的每一个线程在空闲指定时间(keepAliveTime
)过后,释放线程Executors.newCachedThreadPool();
core是0,所有都可回收Executors.newFixedThreadPool();
固定大小,core=maxExecutors.newSingleThreadExecutor();
定时任务的线程池Executors.newScheduledThreadPool();
单线程的线程池,后台从队列里面获取任务,挨个执行import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
public class CompletableFutureTest {
private static ExecutorService executor = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
//方式1、无返回值
CompletableFuture.runAsync(()->log.info("runAsync"),executor);
// 方式2、有返回值
CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
log.info("supplyAsync");
return "supplyAsync";
}, executor);
//获取返回值
try {
String res = supplyAsync.get();
log.info("返回值:{}",res);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(
() -> {
log.info("创建...");
return 10 / 0;
}, executor)
//处理完成后用当前线程处理,如果为whenCompleteAsync,则用其他线程处理
.whenComplete((res, e) -> {
log.info("结果:{},异常:{}", res, e);
})
//出现异常后的回调
.exceptionally((throwable) -> {
log.info("出现异常,返回0,异常:{}", throwable.getCause().toString());
return 0;
});
//打印结果
try {
log.info("结果:{}",supplyAsync.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(
() -> {
log.info("创建...");
return 10 / 2;
// return 10 / 0;
}, executor)
//参数:BiFunction super T, Throwable, ? extends U> fn;接收结果、异常,返回新结果
.handle((res, e) -> {
if (res != null) {
log.info("结果不为空");
return res * 2;
}
if (e != null) {
log.info("有异常");
return 0;
}
log.info("其他情况");
return 0;
});
//打印结果
try {
log.info("结果:{}", supplyAsync.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
基本方法:
现实现一个需求:
代码:
private static void 线程池串行方法() {
CompletableFuture.supplyAsync(
() -> {
log.info("任务1...");
return 111;
})
//获取结果,返回新结果(类型可不同)
.thenApplyAsync((res) -> {
log.info("任务2...获取到上一个的结果:{}", res);
return "222";
}, executor)
//获取上一个结果,但不返回结果
.thenAccept((res) -> {
log.info("任务3...获取到上一个的结果:{}", res);
})
//既不获取,也不返回
.thenRunAsync(() -> {
log.info("任务4...无法获取到上一个的结果");
}, executor);
// 在测试包下运行,线程睡眠,防止提前结束
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
thenCombine
:组合两个future,获取两个future的返回结果,并返回当前任务的返回结果thenAcceptBoth
:组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值runAfterBoth
:组合两个future,不需要获取future的结果,只需两个future处理完任务后处理任务Async
,表示新开一个线程,例如:thenCombineAsync
示例:使用第三个任务,获取前两个任务的返回结果,并进行拼串,返回最终结果:
//两个任务
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(
() -> {
log.info("任务1...");
return 111;
}, executor);
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(
() -> {
log.info("任务2...");
return 222;
}, executor);
//任务3在前两个执行完后执行:
CompletableFuture<String> cf3 = cf1.thenCombineAsync(cf2, (f1, f2) -> {
log.info("任务3...获取到的结果:{},{}", f1, f2);
return f1 + "" + f2;
}, executor);
//打印任务3的结果
try {
log.info("任务3的返回值:{}",cf3.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
applyToEither
:两个任务有一个执行完成,获取它的返回值,处理任务并由新返回值acceptEither
:两个任务有一个执行完成,获取它的返回值,处理任务,但无返回值runAfterEither
:两个任务有一个执行完成,不获取它的返回值,处理任务,也没有返回值Async
以下测试三种方式:
//两个任务
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(
() -> {
log.info("任务1...");
return 111;
}, executor);
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(
() -> {
log.info("任务2...开始");
try {
Thread.sleep(2000);
log.info("任务2...结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 222;
}, executor);
//=========方式1=========
//任务3在前两个执行完后执行:
CompletableFuture<Integer> cf3 = cf1.applyToEitherAsync(cf2, (f1) -> {
log.info("任务3-1...获取到的结果:{},并把结果扩大2倍", f1);
return f1 * 2;
}, executor);
//打印cf3的结果
try {
log.info("任务3-1的返回值:{}", cf3.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//=========方式2=========
cf1.acceptEitherAsync(cf2, (f1) -> {
log.info("任务3-2获取到的结果:{}", f1);
}, executor);
//=========方式3=========
cf1.runAfterEitherAsync(cf2,
() -> log.info("任务3-3:前两个任务有一个完成了"),
executor);
CompletableFuture中有两个静态方法:
代码示例:
//两个任务
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(
() -> {
log.info("任务1...");
return 111;
}, executor);
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(
() -> {
log.info("任务2...开始");
try {
Thread.sleep(2000);
log.info("任务2...结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 222;
}, executor);
//一个完成即可:
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(cf1, cf2);
try {
log.info("有一个任务完成了,返回值:{}",anyOf.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
//都要完成:
CompletableFuture<Void> allOf = CompletableFuture.allOf(cf1, cf2);
try {
log.info("任务都完成了,返回值:{},{}",cf1.get(),cf2.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}