初识线程池

线程池的优势

降低资源消耗

提高响应速度

提高线程的可管理性

使用

首先继承ThreadPoolExecutor

public class PoolThread extends ThreadPoolExecutor {

    public PoolThread(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public PoolThread(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public PoolThread(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public PoolThread(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    public static final Integer CORE_POOL_SIZE = 20;
    
    public static final Integer MAX_POOL_SIZE = 100;
    
    public static final long KEEP_ALIVE = 20;
    
    BlockingQueue<Runnable> poolWorkQueue;
    public void run(){
        // 创建
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,MAX_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS,poolWorkQueue);
    
        // 提交任务
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                // 这里是需要执行的任务
            }
        });
            
        // close
        threadPool.shutdown();
        threadPool.shutdownNow();
    
    }
}
  • corePoolSize(必需)

    核心线程数。默认情况下,核心线程会一直存活,但是当将allowCoreThreadTimeout设置为true时,核心线程也会超时回收。

  • maximumPoolSize(必需)

    线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。

  • keepAliveTime(必需)

    线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将allowCoreThreadTimeout设置为true时,核心线程也会超时回收。

  • unit(必需)

    指定keepAliveTime参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。

  • workQueue(必需)

    任务队列。通过线程池的execute()方法提交的Runnable对象将存储在该参数中。其采用阻塞队列实现。

  • threadFactory(可选)

    线程工厂。用于指定为线程池创建新线程的方式。

  • handler(可选)

    拒绝策略。当达到最大线程数时需要执行的饱和策略。

工作流程

线程工厂 ThreadFactory

实现ThreadFactory接口,并且实现接口下的newThread(Runnable r)方法,不用指定参数

private static class DefaultThreadFactory implements ThreadFactory{
        
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private static final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup():
                Thread.currentThread().getThreadGroup();
        namePrefix = "pool-"+
                    poolNumber.getAndIncrement() +
                "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group,r,
                    namePrefix+threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority()!=Thread.NORM_PRIORITY);
        return t;
    }
}

拒绝策略(handler)

当线程池的线程数达到最大线程数时,需要执行拒绝策略。

实现RejectedExecutionHandler接口,并实现rejectedExecution(Runnable r, ThreadPoolExecutor executor)方法。

  • AbortPolicy(默认)

    丢弃任务并抛出RejectedExecutionException异常。

  • CallerRunsPolicy

    由调用线程处理该任务。

  • DiscardPolicy

    丢弃任务,但是不抛出异常。可以配合这种模式进行自定义的处理方式。

  • DiscardOldestPolicy

    丢弃队列最早的未处理任务,然后重新尝试执行任务。

功能线程池

  1. 定长线程池(FixedThreadPool)
  2. 定时线程池(ScheduledThreadPool )
  3. 可缓存线程池(CachedThreadPool)
  4. 单线程化线程池(SingleThreadExecutor)

定长线程池(FixedThreadPool)

源码分析

public class a{
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
}
  • 特点:

    只有核心线程,线程数量固定,执行完立即回收,任务队列为链表结构的有界队列。

  • 应用场景:

    控制线程最大并发数。

example

public class b{
    public void dingChang(){
        // 1.创建定长线程池对象 & 设置线程池线程数量固定为3
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        // 2.创建好Runnable类线程对象 & 需执行的任务
        Runnable task = new Runnable() {
            @Override
            public void run() {
                System.out.println("开始执行");
            }
        };
        // 3.向线程池提交任务
        fixedThreadPool.execute(task);
    }
}

定时线程池(ScheduledThreadPool)

源码分析

public class a{
    private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
     
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }
     
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
    public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue(), threadFactory);
    }
}
  • 特点:

    核心线程数量固定,非核心线程数量无限,执行完闲置10ms后回收,任务队列为延时阻塞队列。

  • 应用场景:

    执行定时或周期性的任务。

example

public class b{
    public void dingShi(){
        // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        // 2. 创建好Runnable类线程对象 & 需执行的任务
        Runnable task =new Runnable(){
            public void run() {
               System.out.println("执行任务啦");
            }
        };
        // 3. 向线程池提交任务
        scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务
        scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务
    }   
}

可缓存线程池(CachedThreadPool)

源码分析

public class a{
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }
}
  • 特点:

    无核心线程,非核心线程数量无限,执行完闲置60s后回收,任务队列为不存储元素的阻塞队列。

  • 应用场景:

    执行大量、耗时少的任务。

example

public class b{
    public void huCun(){
        // 1. 创建可缓存线程池对象
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        // 2. 创建好Runnable类线程对象 & 需执行的任务
        Runnable task =new Runnable(){
            public void run() {
               System.out.println("执行任务啦");
            }
        };
        // 3. 向线程池提交任务
        cachedThreadPool.execute(task);
    }
}

单线程化线程池(SingleThreadExecutor)

源码分析

public class a{
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
}
  • 特点:

    只有1个核心线程,无非核心线程,执行完立即回收,任务队列为链表结构的有界队列。

  • 应用场景:

    不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作、文件操作等。

example

public class b{
    public void dxc(){
        // 1. 创建单线程化线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        // 2. 创建好Runnable类线程对象 & 需执行的任务
        Runnable task =new Runnable(){
            public void run() {
               System.out.println("执行任务啦");
            }
        };
        // 3. 向线程池提交任务
        singleThreadExecutor.execute(task);
    }
}

END

Executors的4个功能线程池虽然方便,但现在已经不建议使用了,而是建议直接通过使用ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

其实Executors的4个功能线程有如下弊端:

  • FixedThreadPool和SingleThreadExecutor:主要问题是堆积的请求处理队列均采用LinkedBlockingQueue,可能会耗费非常大的内存,甚至OOM。
  • CachedThreadPool和ScheduledThreadPool:主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值