线程池
线程池三大方法
四种拒绝策略
CPU密集型和IO密集型
ForkJoin详情
异步回调
线程池
- 运行程序的本质,占用系统资源。优化资源的使用->池化技术
- 三大方法、七大参数、四种拒绝策略
池化技术
- 实现准备一些资源,有人要用,从这里拿出去,用完后放回来
线程池技术
- 降低资源消耗
- 提高响应速度
- 方便管理
- 线程复用,可以控制最大并发数,管理线程
线程池3大方法
源码分析
//核心线程数
//最大线程数
//超时等待
//超时等待时间单位
//阻塞队列(候客区)
//线程工厂
//拒绝策略
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
this.mainLock = new ReentrantLock();
this.workers = new HashSet();
this.termination = this.mainLock.newCondition();
if (corePoolSize >= 0 && maximumPoolSize > 0 && maximumPoolSize >= corePoolSize && keepAliveTime >= 0L) {
if (workQueue != null && threadFactory != null && handler != null) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
} else {
throw new NullPointerException();
}
} else {
throw new IllegalArgumentException();
}
}
四种拒绝策略
import java.util.concurrent.*;
/**
* Executor 工具类、3大方法
*/
/**
* 四种拒绝策略
* new ThreadPoolExecutor.AbortPolicy()银行满了,还有人要进去,不处理,抛出异常
* new ThreadPoolExecutor.CallerRunsPolicy() 哪来的去哪里
* new ThreadPoolExecutor.DiscardPolicy() 队列满了不会抛出异常
* new ThreadPoolExecutor.DiscardPolicy() 队列满了
*/
public class Demo01 {
public static void main(String[] args) {
//单个线程
//ExecutorService threadPool = Executors.newSingleThreadExecutor();
//ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建5个现成的线程池
//ExecutorService threadPool = Executors.newCachedThreadPool(); //可伸缩的,遇强则强,遇弱则弱
//核心线程数
//最大线程数
//超时等待
//超时等待时间单位
//阻塞队列(候客区)
//线程工厂
//拒绝策略
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
try {
//最大承载:Deque + max
//超过抛出异常
for (int i = 0; i < 9; i++) {
//使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭线程池
threadPool.shutdown();
}
}
}
小结和拓展
- 定义最大线程
1、CPU密集型 几核就定义为几,可以保持CPU效率最高
2、IO密集型 > 程序中十分耗IO的线程,一般可以设置为耗IO资源线程的2倍
//获取当前运行机器的线程数
Runtime.getRuntime().availableProcessors()
ForkJoin详情
- ForkJoin再jdk1.7之后,并行执行任务,提高效率,适合大数据量
- 把大任务拆分为小任务
- 特点:工作窃取(可以提高效率)
import java.util.concurrent.RecursiveTask;
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start;
private Long end;
//临界值
private Long temp = 10000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
//计算方法
@Override
protected Long compute() {
if (end - start > temp) {
Long mid = (start + end) / 2;
ForkJoinDemo task1 = new ForkJoinDemo(start, mid);
task1.fork(); //拆分任务,把任务压入线程队列
ForkJoinDemo task2 = new ForkJoinDemo(mid + 1, end);
task2.fork(); //拆分任务,把任务压入线程队列
return task1.join() + task2.join();
} else {
Long sum = 0L;
for (Long i = start; i <= end; i++) {
sum += i;
}
return sum;
}
}
}
forkjoin案例
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test {
public static void main(String[] args) {
test3();
}
//普通程序员
public static void test1() {
Long sum = 0L;
Long start = System.currentTimeMillis();
for (Long i = 1L; i <= 10_0000_0000; i++) {
sum += i;
}
Long end = System.currentTimeMillis();
System.out.println("sum = " + sum + "时间:" + (end - start));
}
//forkjoin
public static void test2() {
Long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
//创建一个对象
ForkJoinTask<Long> task = new ForkJoinDemo(0L, 10_0000_0000L);
ForkJoinTask<Long> submit = forkJoinPool.submit(task); //提交任务
try {
Long sum = submit.get();
Long end = System.currentTimeMillis();
System.out.println("sum = " + sum + "时间:" + (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
/**
* 使用stream并行流
*/
public static void test3() {
Long start = System.currentTimeMillis();
Long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long :: sum);
Long end = System.currentTimeMillis();
System.out.println("sum = " + sum + "时间:" + (end - start));
}
}
异步回调
- Future设计的初衷,对将来的某个事件的结果进行建模
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* 异步调用:Ajax
*/
public class Demo01 {
public static void main(String[] args) {
//发起一个请求
//runAsync 无返回值的异步回调
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "runAsync=void");
});
System.out.println("1111");
//获取阻塞执行结果
try {
completableFuture.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//有返回值的异步回调
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + "supplyAsync=Integer");
return 1024;
});
try {
System.out.println(completableFuture1.whenComplete((t, u)->{
System.out.println("t=" + t); //正常的返回结果
System.out.println("u=" + u); //错误信息
}).exceptionally((e)->{
e.printStackTrace();
return 223; //可以获取到错误的返回结果
}).get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}