Java线程池浅析

85 阅读3分钟

1、ThreadPoolExecutor 的类关系

1、1 举例说明

  • Java线程池就像一个公司里的员工,公司最多容纳人数最大线程数,这个公司有固定数量的员工核心线程数),但是可以招临时外包最大线程数减去核心数)。有一个待执行的任务清单看板工作队列)。线程空闲时间就是外包员工多久没活就请走。

  • 来活了来活了,首先把活给固定员工,然后固定员工手上都有活,就放到任务清单看板上,都塞满了。只能招点临时外包干。如果还是满了就看拒绝策略了。

  • 拒绝策略

    • (1)AbortPolicy:直接抛出异常,默认策略;
    • (2)CallerRunsPolicy:用调用者所在的线程来执行任务;
    • (3)DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
    • (4)DiscardPolicy:直接丢弃任务;
  • 使用Java线程池的好处是,公司可以更好地管理员工和任务,避免员工过多或者任务过多的情况,提高工作效率。同时,因为员工不是每次都需要重新招聘,所以公司的成本也会降低。

1、2 代码和图解

ThreadPoolExecutor executor = new ThreadPoolExecutor(
        5, // corePoolSize
        10, // maximumPoolSize
        60, // keepAliveTime
        TimeUnit.SECONDS, // time unit for keepAliveTime
        new ArrayBlockingQueue<Runnable>(10), // work queue
        new ThreadPoolExecutor.DiscardPolicy() // rejection policy
);

image.png

1、3 提交任务

  • execute 方法不要方返回值,不知道是否执行成功。
  • submit 会返回Future类型,
    • mFuture.get()会阻塞直到任务完成。
    • mFuture.get(1000,TimeUnit.SECONDS)会阻塞直到任务完成,如果时间到了任务没跑完依旧会返回
Future<?> mFuture = executor.submit(t);
mFuture.get();
mFuture.get(100000,TimeUnit.SECONDS);

1、4 关闭线程

  • shutdown:将线程池设置为SHUTDOWN状态,让它不再接收新任务。
  • shutdownNow:将线程池设置为STOP状态,不再接收新装填,并向执行和暂停中的线程执行interrupt方法。interrupt方法不直接停止。
    • interrupt方法线程内有InterruptedException或者Exception才能中断成功
    • 会返回所有所有没有正在执行任务的线程。
        List<Runnable> runnables = executor.shutdownNow();

1、5 合理配置线程池

-Runtime.getRuntime().availableProcessors()获取CPU个数N

  • CPU密集型: 配置N+1
  • IO密集型:配置2N

2、线程池种类

看下我的代码运行一下就知道了 JavaDemo/src/main/java/com/example/javademo/thread/threadpool · wangxiangqi/JavaStudyDemo - 码云 - 开源中国 (gitee.com)

类型别名池内线程特点场景
FixedThreadPool定长线程池核心线程和最大线程一样多1、核心线程空闲也不会回收除非被关闭。 2、当线程都在干活,其余任务会待在阻塞队列。知道有线程空闲出来。 3、任务是无界的LinkedBlockingQueue控制线程最大并发数new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
CachedThreadPool可缓存线程池核心线程为0,最大线程数为int最大值1、优先利用闲置处理新任务 2、无线程就新建 3、闲置超过一分钟才回收执行数量多耗时少的任务new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
ScheduledThreadPool定时线程池核心线程为传入值,非核心线程为int最大值1、非核心线程闲置时会立马回收指定定时/周期性任务super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue());
SingleThreadExecutor单线程池核心和最大都是11、保证所有任务按照顺序在一个线程中执行 2、不需要处理线程同步问题单线程return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));