线程池的作用
线程的流程和原理
线程池的创建
线程学习的第二篇学习讲过线程池的创建,使用的是google的guava
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
Java提供的线程池
这里是使用java先使用java自带的几种创建线程池的方式,直接看demo:
private static void initThreadPool() {
// 一个线程池,5个工作线程
// ExecutorService threadPool = Executors.newFixedThreadPool(5);
// 一个线程池,1个工作线程
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
// 时间调度,可做定时
// ExecutorService threadPool = Executors.newScheduledThreadPool(5);
// ExecutorService threadPool = Executors.newWorkStealingPool();
// 一个线程池, N个工作线程
ExecutorService threadPool = Executors.newCachedThreadPool();
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t办理业务");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
上面demo中有五种java提供的线程池,都能正常使用,但是不推荐这样子做,阿里巴巴规范手册里面也不推荐这种做法,看看源码就知道了:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
这里的默认最大线程数Integer最大值,很容易造成错误操作导致的线程积压,最后会导致OOM,详细的规范和其他需要注意的地方可以参考阿里巴巴开发手册。
根据这段代码我们可以看出其底层使用的是:
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
其他几种创建方式也是如此,可以点击源码参阅,这里就不粘贴了。
根据这个我们便可知道,我们可以自己手动创建线程池;
自定义创建线程池
public static void main(String[] args) {
// 查看自己电脑上的核心线程数
System.out.println(Runtime.getRuntime().availableProcessors());
ExecutorService threadPool = new ThreadPoolExecutor(2,
5,
2L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t办理业务");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
// initThreadPool();
}
可以自行跑一下代码,看结果,多测几个临界值(7、8、9);
这些参数的意思:
主要讲下第7个参数,handler,主要分为四种:
线程满了之后的策略:
- AbortPolicy:直接抛出RejectedExecutionException异常,组织系统正常运行
- CallerRunsPolicy: "调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量
- DiscardOldestPolicy: 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试在次提交当前任务
- DiscardPolicy: 默默丢弃无法处理的任务,不予任何处理,也不抛出异常。如果允许任务丢失,这就是最好的策略
可以参考源码:
public static class CallerRunsPolicy implements RejectedExecutionHandler{
...
}
public static class AbortPolicy implements RejectedExecutionHandler{
...
}
...
谢谢大家阅读!!