线程池的理解

博客摘抄自 : https://www.cnblogs.com/Krloypower/p/9848018.html

线程池

​ 在项目中提前创建好几个线程,当有任务来的时候,直接用创建好的线程来处理任务,处理完之后,线程不会销毁,等待下一个任务。由于创建和销毁线程很消耗性能。所以可以用线程池来提高性能。

自己踏入过的误区,在一个类里面,把线程池当作了改类的成员变量,用完之后没有shutdown。

eg1:

// 错误写法
public class test{
  private ThreadPoolExecutor excutor
  ......
}

每次新建改对象,都会创建一个线程池,这样会导致资源耗尽,出现OOM。

eg2:

误区2 ,在一个类中,设置一个静态变量的线程池,这个类共用一个线程池。用完之后没有shutdown。

// 错误写法
public class test{
  private static ThreadPoolExecutor excutor
  ......
}

这样的写法有点狭隘,只在当前类中,浪费资源。 

要补充的是,若是使用线程池资源的话,就不用shutdown线程了。shutdown只是给队列的线程发interrupt 不能接受新任务 但等待老任务结束  。

其实这个要看具体情况而言,比如对于一类资源使用一个线程池,然后不关闭掉。在关服之前关闭掉线程池,在比如1到2点接受任务,2点之后不接受任务,那么2点关闭掉线程池等等。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corePoolSize : 核心池大小,线程池允许的线程数量
  • maximumPoolSize:最大池大小,当核心池中的线程数量满了,并且BlockingQueue队列已满,这个时候又来了一个任务。就会新建一个线程执行该任务,一直到线程池的线程数量达到maximumPoolSize大小,如果这时再来一个任务,就会调用相应的拒绝策略。当线程池的任务降低到只需要corePoolSize的线程数一下,就会根据keepAliveTime ,回收大于corePoolSize的多余的线程。
  • keepAliveTime:当线程池中的数据大于corePoolSize时,多余的线程没有任务进来的时候,根据这个时间大小回收。
  • unit:回收时间大小
  • workQueue:阻塞队列类型
  • threadFactory:线程池工程
  • handler:拒绝策略
public class ThreadPoolExecutorUtil {

    // 线程池 单例化:全局唯一配置
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(10,20,
            60L,TimeUnit.SECONDS,
            new SynchronousQueue<>(),Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public ThreadPoolExecutorUtil(){};

    public static ThreadPoolExecutor getInstance(){
        return executor;
    }


}

其实,为了线程安全,上面的Thread是典型的饿汉式的,线程是安全的,我们还可以把初始化工作也完成掉,直接在启动类的下方加上此static的实例化:

    public static void main(String[] args) {
        ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(ReportServerApplication.class, args);
        // 解决websocket 当中无法注入bean的方法
        ImportDictValueSocket.setApplicationContext(configurableApplicationContext);
        ThreadPoolExecutorUtil.getInstance();    // 让其直接实例化掉 
    }

 

posted @ 2018-11-05 22:43  白云是世界的公民  阅读(101)  评论(0)    收藏  举报