创建线程池

使用Executors可以查看所有的JDK封装好的线程池

public static void main(String[] args) {
    // 1、定长线程池
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
    
    // 2、可缓存线程池
    ExecutorService catchThreadPool = Executors.newCachedThreadPool();

    // 3、单线程线程池
    ExecutorService singleThread = Executors.newSingleThreadExecutor();

    // 4、定时线程池
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);

    // 5、单线程定时线程池
    ScheduledExecutorService singleThreadScheduled = Executors.newSingleThreadScheduledExecutor();

    //6、 任务窃取线程池
    ExecutorService workStealingPool = Executors.newWorkStealingPool();
}

1、定长线程池源代码:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

(1)核心线程数量等于最大线程数量,一旦被创建指定的线程数量,就不会被垃圾回收,除非显式地调用了线程池的shutdown或shutdownNow方法来关闭线程池。
(2)默认为无界任务队列

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}

2、可缓存线程池,源代码

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

(1)没有核心线程,不限制线程数量,空闲线程超过60秒不工作会被回收
(2)直接提交队列,来了任务就创建线程,创建和销毁线程会浪费大量时间

3、单线程线程池

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

(1)只有一个核心线程,是一个无界队列
(2)好处是避免了并发问题
4、定时线程池

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

(1)不限制线程数量,一旦线程空闲下来会立马被销毁
(2)DelayedWorkQueue,阻塞队列

5、单线程定时线程池

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

6、任务窃取线程池

public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool
        (Runtime.getRuntime().availableProcessors(),
         ForkJoinPool.defaultForkJoinWorkerThreadFactory,
         null, true);
}

线程池的核心组成部分及其运行机制

  • (1)corePoolSize:指定线程池中,核心线程的数量
  • (2)maximumPoolSize:指定线程池中,最大线程数量
  • (3)keppAliveTime:当线程池线程的数量超过 corePoolSize 时,多余的空闲线程的存活时长,即空闲线程在多长时间内销毁
  • (4)unit:是 keppAliveTime 时长单位
  • (5)workQueue:任务队列,把任务提交到该任务队列中等待执行
  • (6)ThreadFactory:线程工厂,用于创建线程
  • (7)handler:拒绝策略,当任务太多,来不及处理时,如何拒绝

workQueue工作队列是指提交未执行的任务队列,它是BlockingQueue接口的对象,仅用于存储Runnable任务。根据队列功能分类,在ThreadPoolExecutor构造方法中可以使用以下几种阻塞队列:
(1)直接提交队列:由 SynchronousQueue 对象提供,该队列没有容量,提交给线程池的任务不会被真实的保存,总是将新的任务提交给线程执行,如果没有空闲线程,则尝试创建新线程,如果线程数量已经达到 maximumPoolSize 规定的最大值则执行拒绝策略。
该线程池在极端情况下,每次提交新的任务都会创建先拿到线程执行,适合用来执行大量耗时短并且提交频繁的任务。
(2)有界任务队列:由 ArrayBlockingQueue 实现,在创建 ArrayBlockingQueue 对象时,可以知道一个容量,当有任务需要执行时,如果线程池中线程数小于 corePoolSize 核心线程数,则创建新的线程;如果大于核心线程数则加入等待队列,如果队列已满则无法加入,在线程数小于 maximumPoolSize 指定的最大线程数前提下会创建新的线程来执行,如果线程数大于 maximumPoolSize 则执行拒绝策略。
(3)无界任务队列:由 LinkedBlockingQueue 对象实现,与有界队列相比,除非系统资源耗尽,否则无界队列不存在任务失败的情况,当有新的任务时,在系统线程数小于 corePoolSize 核心线程数则创建新的线程来执行任务;当线程池中线程数量大于 corePoolSize 核心线程数则把任务加入阻塞队列。
(4)优先任务队列:由 PriorityBlockingQueue 实现,是带有任务优先级的队列,是一个特殊的无界队列,不管是 ArrayBlockingQueue 队列,还是 LinkedBlockingQueue 队列都是按照先进先出算法处理任务的,在 PriorityBlockingQueue 队列中可以根据任务优先级顺序先后执行。

ThreadFactory
ThreadFactory 是一个接口,只有一个用来创建线程的方法:
Thread newThread(Runnable r);
当线程池中需要创建线程时就会调用该方法。
通过 new ThreadFactory() 来自定义线程工厂。

拒绝策略
ThreadPoolExecutor构造方法的最后一个参数指定了拒绝策略,当提交给线程池的任务量超过实际承载能力时,如何处理?
即线程池汇中的线程已经用完了,等待队列也满了,无法为新提交的任务服务,可以通过拒绝策略来处理这个问题。JDK提供了四种拒绝策略:
(1)AbortPolicy:抛出异常
(2)CallerRunsPolicy:只要线程池没有关闭,会在调用者线程中运行当前被丢弃的任务
(3)DiscardOldestPolicy:将任务队列中最老的任务丢弃,尝试再次提交任务
(4)DiscardPolicy:直接丢失这个无法处理的任务
Executors 工具类提供的静态方法返回的线程池默认的拒绝策略是 AbortPolicy,抛出异常。
通过 new RejectedExecutionHandler() 来自定义拒绝策略。

自定义线程池

package threadpool;

import java.util.concurrent.*;

public class CustomizeThreadPool {

    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 100, 30, TimeUnit.SECONDS, new ArrayBlockingQueue(101));

        for(int i=0; i<101; i++){
            final int index = i;
            pool.execute(new Thread(new Runnable() {
                public void run() {
                    System.out.println(index + "被执行线程名:" + Thread.currentThread().getName());
                }
            }));
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二次觉醒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值