线程池是什么?线程池(ThreadPoolExecutor)使用详解

点一点,了解更多https://www.csdn.net/

本篇文章将详细讲解什么是线程池,线程池的参数介绍,线程池的工作流程,使用Executors创建常见的线程池~~~

目录

点一点,了解更多

文章目录

一、线程池的概念

1.1线程池的目的-提高效率

二、线程池的参数介绍

2.1线程池的拒绝策略

以上四种策略要重点掌握,面试常考~~

三、线程池的工作流程

四、线程池的创建

4.1方法一 

 4.2方法二 

4.3方法三

4.4方法四

4.5方法五

4.6方法六

4.7方法七

五、模拟实现一个线程池

一、线程池的概念

简单来说,可以理解为一个“现成的池子”,里面有一定数量的线程等待工作,每次使用不用再次创建、使用完了不用马上销毁,会自动回收进池子中。类似常量池等等~~

虽然创建销毁线程比创建销毁进程更轻量, 但是在频繁创建销毁线程的时候还是会比较低效,线程池就是为了解决这个问题,如果某个线程不再使用了,并不是真正把线程释放,而是放到一个“池子”中,下次如果需要用到线程就直接从池子中取,不用再次创建。

1.1线程池的目的-提高效率

池的目的就是为了提高效率,从线程池中拿线程,属于用户态操作;而从系统再去创建线程,涉及到用户态和内核态之间的切换,真正的创建是在内核态完成的。

那么什么是用户态?什么是内核态?下面我来举个例子:

银行中有大厅和服务柜台,大厅相当于用户态,柜台相当于内核态;每个地方都有打印机,如果来客户需要办理业务,可以在打印机上办理,也可以找工作人员办理。

此时来个老哥,说想办个银行卡,但是没带身份证复印件,有俩个办法:1.自己去大厅的复印件,自己复印一份,拿过来。2.让工作人员去柜台里面的打印机,去复印下再拿回来。

那么如果自己去复印,就立即去了,立即回来了,中间不耽误;如果工作人员去复印,他可能会做点别的,确实能给你复印,但是就不一定及时了~~

结论:用户态操作,时间是可控的;涉及到内核态操作,时间就不可控了~~

二、线程池的参数介绍

先看ThreadPoolExecutor 的构造方法

重点理解一下这几个参数含义:先情景带入一下,把线程池当作公司,一类正式员工;一类实习生;

1.corePoolSize:核心线程数,相当于正式员工

2.maxinumPoolSize:最大线程数,相当于正式员工+实习生

3.

long keepAliveTime:实习生线程保持存活的时间 

当任务比较少的时候,整体比较空闲,实习生不是立即被辞退的,表示实习生最大的存活时间

4.

TimeUnit unit:单位,秒,分钟,毫秒

5. 

BlockingQueue<Runnable> workQueue:线程池里要管理很多任务,这些任务也是通过阻塞队列来组织的,此时可以手动指定一个队列给线程池,此时就可以很方便的获取队列中的信息

6.

ThreadFactory threadFactory:工厂模式,创建线程的辅助的类

7.

RejectedExecutionHandler handler:线程池的拒绝策略,如果任务量超出公司的负荷接下来该怎么处理

2.1线程池的拒绝策略

上述四种是标准库中提供的四种拒绝策略:

1.

表示如果队列满了,继续添加任务, 添加操作之间抛出异常(新老都执行不了,哭)

2.

添加的线程自己负责执行这个任务(怼回去)

3.

丢弃最老的任务

4. 丢弃最新的任务 

以上四种策略要重点掌握,面试常考~~

三、线程池的工作流程图

四、线程池的创建

  • ExecutorService 表示一个线程池实例
  • Executors 是一个工厂类, 能够创建出几种不同风格的线程池
  • ExecutorService 的 submit 方法能够向线程池中提交若干个任务
  • Executors 本质上是 ThreadPoolExecutor 类的封装

4.1方法一 

创建具有十个线程的线程池(大小固定)

public class ThreadDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
    }
}

 4.2方法二 

创建一个操作无界队列且只有一个工作线程的线程池

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

4.3方法三

用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存,创建线程数目动态增长的线程池

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

4.4方法四

创建一个单线程执行器,可以在给定时间后执行或定期执行。

 ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();

4.5方法五

创建一个指定大小的线程池,可以在给定时间后执行或定期执行,是进阶版的Timer

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

4.6方法六

 创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务,不保证处理顺序

Executors.newWorkStealingPool();

4.7方法七

自定义线程池,工作中使用这种方法创建线程池

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,
                10,
                10000,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());

五、模拟实现一个线程池

设置一个具有十个线程的线程池,打印0-1000个数。

其中在构造方法中调用十个线程执行,submit方法进行放入任务!!

class MyThreadPool{
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }

    public MyThreadPool(int n){
        for (int i = 0; i < n; i++) {
            Thread t = new Thread(() -> {
                try {
                    while (true){
                        Runnable runnable = queue.take();
                        runnable.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            t.start();
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            int number = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello "+ number);
                }
            });
        }
        Thread.sleep(3000);
    }
}

可见,线程池中任务的执行的顺序和添加顺序不一定相同,因为这十个线程是无序调度的

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月11日
下一篇 2023年12月11日

相关推荐