线程池学习总结

线程池学习总结

关于线程状态的学习文章链接
什么是线程池

线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理。
如果每个请求都创建一个线程去处理,那么服务器的资源很快就会被耗尽,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

线程池状态:

  • RUNNING:运行状态,这个状态下可以接受任务来处理
  • SHUTDOWN:待关闭状态,这个状态下不会在接受新任务,但是仍然会处理阻塞队列中的任务,当阻塞队列中的任务为空,并且工作线程数为0时,进入
    TIDYING 状态
  • STOP:停止状态,不会接受新任务,并且也不处理阻塞队列中的任务,并且会尝试结束执行中的任务,当阻塞队列为空,并且工作线程数为0时,进入
    TIDYING 状态
  • TIDYING:整理状态,此时任务都已经执行完毕,并且也没有工作线程执行 terminated 方法后进入 TERMINATED 状态
  • TERMINATED:终止状态,此时线程池完全终止了,并完成了所有资源的释放

在这里插入图片描述
线程池参数:
核心线程数、最大线程数、阻塞队列,时间、拒绝策略。

线程池如何处理任务的?
当程序提交一个任务时,线程池会比较当前工作线程数和核心线程数,如果前者小于后者,线程池直接新建一个线程来处理这个任务,如果前者大于后者,则会将这个任务放到阻塞队列中等待被处理,如果队列满了,线程池会建立“临时”工作线程来处理队列的任务,如果工作线程数达到最大线程数,线程池会做出拒绝策略。
ps:当工作线程数量大于核心线程数,线程池会回收掉那些线程等待任务时间超时的线程,这里就要关系到使用task()、poll()方法的区别了

拒绝策略

  • 抛出异常(默认)
  • 调用者线程来处理这个任务
  • 从阻塞队列中找最老的任务,将其丢弃,然后提交该任务
  • 将请求任务丢弃

AbortPolicy – 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException异常。
CallerRunsPolicy --当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。
DiscardOldestPolicy --当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。
DiscardPolicy – 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。

java.util.concurrent.Executors常用的几种线程池类型

  • newSingleThreadExecutor:一个单线程的线程池,可以用于需要保证顺序执行的场景,并且只有一个线程在执行。
  • newFixedThreadPool:一个固定大小的线程池,可以用于已知并发压力的情况下,对线程数做限制。(队列)
  • newCachedThreadPool:一个可以无限扩大的线程池,比较适合处理执行时间比较小的任务。
  • newScheduledThreadPool:可以延时启动,定时启动的线程池,适用于需要多个后台线程执行周期任务的场景。

自定义线程池
通过ThreadPoolExecutor来实现自定义的线程池

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,//线程最大生命周期
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) ;

Demo

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.TimeUnit;

/**
*了解上面的参数信息后我们就可以定义自己的线程池了,我这边用ArrayBlockingQueue替换了LinkedBlockingQueue,指定了队列的大小,当任务超出队列大小之后使用CallerRunsPolicy拒绝策略处理。
这样做的好处是严格控制了队列的大小,不会出现一直往里面添加任务的情况,有的时候任务处理的比较慢,任务数量过多会占用大量内存,导致内存溢出。
*/
public class BengHiongThreadPoolExecutor {
    private static ExecutorService executorService = newFixedThreadPool1(50);
    private static ExecutorService newFixedThreadPool1(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(10000), new DefaultThreadFactory(), new CallerRunsPolicy());
    }
    public static void execute(Runnable command) {
        executorService.execute(command);
    }
    public static void shutdown() {
        executorService.shutdown();
    }
    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;
        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "FSH-pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }
        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)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
}

总结:
线程池技术应用在多线程的场景可以节省很多资源消耗,提高性能,要用好先尝尝,要知道他的原理以及一些设定方法,才能更好的运用在实际中。

参考:
https://mp.weixin.qq.com/s/tvxF74r-NO2uiNIBebPjmQ
https://blog.csdn.net/j3T9Z7H/article/details/80730038

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值