线程池的使用

1.什么是线程池

管理线程,避免创建大量的线程增加开销,提高线程响应速度。

2.线程池的处理流程

public ThreadPoolExecutor(int corePoolSize, //核心线程数
                          int maxinumPoolSize, //最大线程数    
                          long keepAliveTime, //超出核心线程数以外的线程空闲后存活时间
                          TimeUnit unit, //存活时间单位
                          BlockingQueue<Runnable> workQueue, //保持待执行的任务的队列
                          ThreadFactory threadFactory, //创建线程使用的工厂(线程名、线程优先级等)
                          RejectedExecutionHandler handler) //当任务无法执行的处理器
                           {
                                   ……
                            }
  • corePoolSize:核心线程数
    在任务小于核心线程时,有任务进来就会创建线程,即使有空闲的线程,超出核心线程后就不在创 建线程了,有空闲的线程就去队列里面取任务

  • maxnumPoolSize:最大线程数
    包括核心线程数+核心以外的数 ,如果任务队列满了,并且池中线程数小于最大线程数,会再创建线程执行任务

  • keepAliveTime:核心池以外的线程存活时间
    如果给线程池设置allowCoreThreadTimeOut(true),则核心线程在空闲时也会在keepAliveTime后被杀死,
    如果任务是多而容易被执行的,可以设置这个参数,那样线程在存活的时间里可以有更大的可能接受新任务

  • BlockingQueue:保存待执行的阻塞队列
    ArrayBlockingQueue:基于数组、有界、按照FIFO(先进先出)原则对元素键排序, LinekdBlockingQueue:基于链表

  • ThreadFactory

  • RejectedExecutionHandler:饱和策略(任务数量大于最大线程数)
    CallerRunPolicy:只有线程池没有关闭,就直接用调用者所在的线程来运行任务
    AbortPolicy:直接抛出RejectExecutionException异常
    DiscardPolicy:把任务丢弃不处理了
    DiscardOldestPolicy:把队列里呆的最久的那个线程丢弃了然后在用execute()尝试再次执行
    自行实现

执行源码解析

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    //获取正在运行的线程数据量
    int c = ctl.get();
    //当前线程池中线程数量比核心数小,新增线程执行任务
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //核心池已满,但任务队列未满,添加到队列中
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        //如果被移除了,拒接任务
        if (! isRunning(recheck) && remove(command))
            reject(command);
         //如果之前的线程已被销毁,新建线程执行任务
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    //核心池已满,队列已满,试着新建线程
    else if (!addWorker(command, false))
        reject(command);//如果创建失败,说明线程池被关闭或者线程池满了,拒绝任务
}

3.JDK提供的线程池

  1. newFixedThreadPool
  2. newCacheThreadPool
  3. newSingleExecutor
  4. newScheduleThreadPool
        /*
         *newFixedThreadPool
         *1.核心数等于最大线程数
         *2.存活时间为0,无意义,因为无其他线程
         *3.阻塞队列使用了LinkedBlockingQueue,大小无限
         *4.执行完的任务会反复从任务队列去取任务
         *  常用于负载比较重的服务器,为了资源合理利用,需要限制当前的线程数
         */
        ExecutorService executors = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 5; i++) {
           //executors.execute(new MyThread());
        }

        /*
         *newCachedThreadPool
         * 1.核心线程为0,全是外包团队
         * 2.最大线程数无限
         * 3.线程存活时间60S
         * 4.阻塞队列为SynchronousQueue
         *流程:直接向SynchronousQueue提交任务,如果有空闲线程就去取任务如果没有就新创建,执行完任务的线程有60s的存活时间
         *     在此期间可以接受任务,超过存活时间就被回收
         * 如果当前提交任务的速度大于执行的速度极端情况下将会创建大量线程耗尽CPU和内存资源
         * 由于有60S的存活时间,长时间保持空闲并不会占用任何资源
         * 用于并发执行大量短暂的小任务,或是负载比较轻的服务器
         */
        ExecutorService cachedExecutors = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
           //cachedExecutors.execute(new MyThread());
        }

        /*
         * newSingleThreadExecutor
         * 1.单线程的线程池,唯一的一个线程不断的从线程池中取任务
         * 适合串行执行的任务
         */
        ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 3; i++) {
           //singleExecutor.execute(new MyThread());
        }

        /*
         * newScheduledThreadPool
         * 周期性、延迟性任务线程池
         * 1.ScheduledFuture schedule=schedule(Runnable command, long delay, TimeUnit unit):delay后执行command任务
         *    schedule.get():这方法会阻塞当前线程直到任务完成,callable
         * 2.ScheduledFuture schedule=schedule(Callable<V>  callable, long delay, TimeUnit unit):delay后执行callable任务
         *   schedule.get():这方法会阻塞当前线程直到任务完成,Callable有返回值
         * 3.scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
         *   command:周期性任务
         *   initialDelay:第一次执行的时间
         *   period:循环执行的时间
         *   unit:执行的时间单位
         *   当任务耗时大于period时,任务执行完毕后将重新等待period时间后再次执行
         * 4.scheduleWithFixedDelay(Runnable command, long initialDelay, long period, TimeUnit unit)
         *   参数与3一致,不同的是当任务耗时大于period时,任务执行完毕后立即执行下一个任务
         */
        ScheduledExecutorService scheduledExecutors = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() * 2);

4.自定义线程池管理类

package com.tr.thread.pool;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
* 作者:tangren on 2019/3/22
* 包名:com.tr.thread.pool
* 邮箱:996489865@qq.com
* TODO:线程池管理类(周期任务+普通任务)
*/

public class ThreadPoolManager {
    //核心线程数
    private static final int coreSize = Runtime.getRuntime().availableProcessors() * 2;
    //最大线程数
    private static final int maxSize = 20;
    //存活时间
    private static final long keepAliveTime = 1L;
    //普通任务线程
    private ThreadPoolExecutor executor;
    //定时任务线程
    private ScheduledExecutorService executorService;
    private Map<String, Future> futureMap = new HashMap<>();
    private AtomicInteger runnableCount = new AtomicInteger(0);
    private volatile static ThreadPoosManager instance = null;

    privateThreadPoolManager() {
        //队列大小为30
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(30);
        ThreadFactory factory = r -> {
            Thread thread = new Thread(r);
            thread.setPriority(Thread.NORM_PRIORITY);
            thread.setName(">_" + runnableCount.getAndIncrement());
            return thread;
        };
        executor = new ThreadPoolExecutor(coreSize, maxSize, keepAliveTime, TimeUnit.SECONDS, queue, factory, new ThreadPoolExecutor.DiscardOldestPolicy());
        executorService = new ScheduledThreadPoolExecutor(coreSize, factory, new ThreadPoolExecutor.DiscardOldestPolicy());
    }

    public static ThreadPoolManager getInstance() {
        if (instance == null) {
            synchronized (ThreadPoolManager.class) {
                if (instance == null) {
                    instance = newThreadPoolManager();
                }
            }
        }
        return instance;
    }

    /**
     * 提交普通任务
     *
     * @param runnable 任务
     */
    public void execute(Runnable runnable) {
        executor.execute(runnable);
    }

    /**
     * 提交有返回的普通任务
     *
     * @param runnable 任务
     * @return .
     */
    public Future<?> submit(Runnable runnable) {
        return executor.submit(runnable);
    }

    /**
     * 执行延时任务
     *
     * @param command 任务
     * @param delay   延时时间
     * @param unit    时间单位
     * @return .
     */
    public ScheduledFuture<?> exeDelayTask(Runnable command,
                                           long delay, TimeUnit unit) {
        return executorService.schedule(command, delay, unit);
    }

    /**
     * @param tag          任务标志
     * @param command      任务
     * @param initialDelay 延迟执行的时间
     * @param period       循环周期
     * @param unit         时间单位
     */
    public void exeCycleTask(String tag, Runnable command,
                             long initialDelay,
                             long period,
                             TimeUnit unit) {
        if (futureMap.get(tag) == null) {
            executorService.scheduleAtFixedRate(command, initialDelay, period, unit);
        }
    }


    /**
     * 停止循环任务
     *
     * @param tag .
     */
    public void stopTask(String tag) {
        Future future = futureMap.get(tag);
        if (future != null && !future.isCancelled()) {
            future.cancel(true);
            futureMap.remove(future);
        }
    }

    /**
     * 关闭周期任务线程池
     */
    public void shutDownCycle() {
        if (!executorService.isShutdown()) {
            executorService.shutdown();
        }
    }

    /**
     * 关闭普通任务线程池
     */
    public void shutDownNormal() {
        if (!executor.isShutdown()) {
            executor.shutdown();
        }
    }

    /**
     * 关闭所有任务
     */
    public void showDownAll() {
        shutDownCycle();
        shutDownNormal();
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

吴唐人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值