java多线程学习(线程池学习)(五)

线程池的作用

线程池的作用

线程的流程和原理

流程图
文字

线程池的创建

线程学习的第二篇学习讲过线程池的创建,使用的是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{
...
}
...

谢谢大家阅读!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章