12、线程池ThreadPool

可莉
• 阅读 544

1、总共有5种线程池:

  • 1、单个线程

    ExecutorService pool1 = Executors.newSingleThreadExecutor();

    12、线程池ThreadPool

  • 2、固定数量线程

    ExecutorService pool2 = Executors.newFixedThreadPool(2);

    12、线程池ThreadPool

  • 3、动态线程数量

    ExecutorService pool3 = Executors.newCachedThreadPool();

    12、线程池ThreadPool

  • 4、定时调度的线程池,功能和timer一样

    ExecutorService pool4 = Executors.newScheduledThreadPool(2);

    12、线程池ThreadPool

    12、线程池ThreadPool

    ScheduledThreadPoolExecutor还是继承了ThreadPoolExecutor

    12、线程池ThreadPool

  • 5、这个不知道是什么线程池

    ExecutorService pool5 = Executors.newWorkStealingPool();

    12、线程池ThreadPool

它们都有execute()、submit()等方法。

12、线程池ThreadPool

12、线程池ThreadPool

在getTask中有这么一段代码

12、线程池ThreadPool

我们执行它的execute()方法其实只是把任务放在它里面的blockingqueue中,这样就会唤醒阻塞的线程拿到task来执行,所以这就需要blockingqueue。这是一个生产者和消费者模型

2、问题:怎么知道queue中的任务怎么运行?

这就需要统一的接口标准,往里面扔的任务必须implements Runable接口才行(为什么?)

因为:只要实现了Runable/callable接口,就必须实现一个run/call方法,这样线程池中的线程就可以直接调用run或者call方法,执行业务。

注意:传入进去的Runnable任务,不会以线程的形式运行。

3、代码实例:

import java.util.ArrayList;
import java.util.concurrent.*;

/**
 * Executors创建线程池
 * ThreadPoolExecutor创建线程池
 *
 * 类的关系
 * class ThreadPoolExecutor extends AbstractExecutorService
 *
 * class AbstractExecutorService implements ExecutorService
 *
 * interface ExecutorService extends Executor
 *
 * [@Author](https://my.oschina.net/arthor) liufu
 * @CreateTime 2018/5/10  15:24
 */
public class ThreadPoolExecutorTest {
    public static void main(String[] args) {

        ExecutorService pool1 = Executors.newFixedThreadPool(2);
        ExecutorService pool2 = Executors.newCachedThreadPool();
        ExecutorService pool3 = Executors.newScheduledThreadPool(2);
        ExecutorService pool4 = Executors.newSingleThreadExecutor();
        ExecutorService pool5 = Executors.newWorkStealingPool();

       //Executors.newXX其实就是创建了new ThreadPoolExecutor()对象,里面传入对应的值而已
       //推荐使用这种方式,对资源好控制
        ExecutorService executor = new ThreadPoolExecutor(2,  //最小线程数        
                2,                         //最大线程数
                0L,                         //执行超时,0L,表示不超时
                TimeUnit.MILLISECONDS,                      //时间为分钟
                new ArrayBlockingQueue<Runnable>(10));        //任务队列的大小

        ArrayList<Runnable> runnables = new ArrayList<>();
        pool1.shutdown();
        //这个就是生产者!!
        for (int i = 0; i < 100; i++) {
            runnables.add(new Runnable() {
                [@Override](https://my.oschina.net/u/1162528)
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName());
                        Thread.sleep(5000);
                        System.out.println("工作完成!!");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
        }

        //消费者!!!
        for (Runnable runnable : runnables) {
            pool1.execute(runnable);
        }

        //主线程是不等待线程池的。
        System.out.println("早就执行完了,不等待线程池的处理了");
    }
}

4、线程池示意图

12、线程池ThreadPool

5、问题

  • 1、为什么需要线程池?

    这个和连接池一样,为了避免频繁的创建和销毁线程池带来的性能损耗。

  • 2、它的execute()方法其实只是把任务放在它里面的BlookingQueue中,然后线程池里面的线程来获取任务执行,如果queue中没有任务就阻塞。

  • 3、线程池创建的方式

  • 3.1、Excutors

    内部new ThreadPoolExcutor(),而且那个任务队列queue是没有指定大小的,默认是Integer.MAX_VALUE = 42亿,如果线程处理的慢,就会导致queue堆满42亿任务对象,会出现内存溢出问题,GC没法扫。

  • 3.2、new ThreadPoolExcutor()这种比较自主可控,里面有7个参数

    • 前面5个比较常用分别是:

        最小线程
        最大线程
        过期时间
        时间单位
        queue(要指定大小)
      
    • 后面是:

        ThreadFactory(可以给线程加名字)
        RejectedExecutionHandler(拒绝执行时的回调)。
      
    • RejectedExecutionHandler已经有好几种实现

        ● AbortPolicy
        ● DiscardPolicy
        ● DiscardOldestPolicy
        ● CallerRunsPolicy
        ● 自定义
      

      12、线程池ThreadPool

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
2年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
2年前
Noark入门之线程模型
0x00单线程多进程单线程与单进程多线程的目的都是想尽可能的利用CPU,减少CPU的空闲时间,特别是多核环境,今天咱不做深度解读,跳过...0x01线程池锁最早的一部分游戏服务器是采用线程池的方式来处理玩家的业务请求,以达最大限度的利用多核优势来提高处理业务能力。但线程池同时也带来了并发问题,为了解决同一玩家多个业务请求不被
Wesley13 Wesley13
2年前
Java 基础知识(七)
1.创建线程池1)newCacheThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程 2)newFixedThreadPool  创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 3)newScheduledThreadPool  创建一个定长线程池,支持
Stella981 Stella981
2年前
Nginx反向代理upstream模块介绍
!(https://oscimg.oschina.net/oscnet/1e67c46e359a4d6c8f36b590a372961f.gif)!(https://oscimg.oschina.net/oscnet/819eda5e7de54c23b54b04cfc00d3206.jpg)1.Nginx反
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这