【JAVAEE】线程池基础知识⭐

目录

1.什么是线程池

2.为什么要使用线程池

3.怎么使用线程池

4.自定义一个线程池

5.为什么不推荐使用系统自带的线程池

5.1线程池构造方法的参数和含义

5.1.1拒绝策略

5.2线程池的工作原理

5.3为什么不适用系统自带的线程池

补充:工厂模式


1.什么是线程池

在JDBC编程中,通过DataSource获取Connection连接的时候就已经用到了的概念,当Java程序需要数据库连接的时候就从池中拿一个空闲的连接对象给Java程序,Java程序用完了连接之后就会返回给连接池。

线程池就是在池中放的是线程本身,当程序启动的时候就创建出若干个线程,如果有任务就处理,没有任务就等待。

百度百科的定义为:

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。

2.为什么要使用线程池

使用线程池可以减少系统创建线程的损耗。

如下图:创建线程需要申请PCB

 线程池的作用就是为了减少这些关于申请和释放PCB的操作,尽量保证我们的程序在用户态执行,不牵扯到硬件层面。

3.怎么使用线程池

JDK给我们提供了一些方法来创建线程池:

        // 1. 用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        // 2. 创建一个操作无界队列且固定大小线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        // 3. 创建一个操作无界队列且只有一个工作线程的线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        // 4. 创建一个单线程执行器,可以在给定时间后执行或定期执行。
        ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        // 5. 创建一个指定大小的线程池,可以在给定时间后执行或定期执行。
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
        // 6. 创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务,不保证处理顺序
        Executors.newWorkStealingPool();

这里使用第2个方法进行基本使用示例:

先创建一个线程池:

//创建一个线程池
ExecutorService threadPoll= Executors.newFixedThreadPool(3);

此时线程池中已经存在了一些创建好的线程,只需要往线程池中提交任务即可。

这里采用for循环,提交十个任务(打印“我是任务几”):

        //提交任务到线程池
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            threadPoll.submit(() -> {
                System.out.println("我是任务 " + taskId + ","+"Thread.currentThread().getName());
            });
        }

 任务被提交到线程池后,任务就会被自动执行。

4.自定义一个线程池

1.可以提交任务到线程池,那么就会有一种数据结构来保存我们提交的任务,这里可以考虑用阻塞队列来保存任务。

2.创建线程池需要指定初始线程数量,这些线程不停的扫描阻塞队列,如果有任务就立即执行。可以考虑使用线程池对象的构造方法,接收要创建线程的数量,并在构造方法中完成线程的创建。

实现过程:

1.定义一个阻塞队列来保存我们的任务

    //1.定义一个阻塞队列
    BlockingDeque<Runnable>queue=new LinkedBlockingDeque<>(3);

2.定义一个方法提交任务

    //2.对外提供一个方法用来往队列中提交任务
    public void submit(Runnable task) throws InterruptedException {
        queue.put(task);
    }

3.定义构造方法

    //3.构造方法,完成线程的创建,扫描队列,取出任务并执行
    public MyThreadPoll(int capacity){
        if(capacity<=0){
            throw new RuntimeException("线程数量不能小于0");
        }
        for (int i = 0; i < capacity; i++) {
            Thread thread=new Thread(()->{
                while(true) {
                    try {
                        //取出任务
                        Runnable take = queue.take();
                        //执行任务
                        take.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            //启动线程
            thread.start();
        }
    }

测试一下代码:

    public static void main(String[] args) throws InterruptedException {
        //创建自定义的线程池
        MyThreadPoll myThreadPoll=new MyThreadPoll(3);
        //往线程池中提交任务
        for (int i = 0; i < 10; i++) {
            int taskId=i;
            myThreadPoll.submit(()->{
                System.out.println("我是任务 " + taskId + ", " + Thread.currentThread().getName());
            });
        }
    }

执行成功,测试通过。

5.为什么不推荐使用系统自带的线程池

5.1线程池构造方法的参数和含义

通过工厂方法获取的线程池,最终都是ThreadPoolExecutor类的对象。

ThreadPoolEexecutor各参数含义:

corePoolSize:核心线程数,创建线程池时包含的最小线程数量

maximumPoolSize:最大线程数,也可以叫做临时线程数,当核心数不够用的时候,允许系统可以创建的最多线程数是多少

keepAliveTime:临时线程空闲的时长

TimeUnit unit:空闲的时间单位,和keepAliveTime配合使用

BlockingQueue<Runnable>workQueue:用来保存任务的阻塞队列

ThreadFactory:线程工厂,如何去创建线程,用系统默认的就可以

RejectedExecutionHandler:拒绝策略,触发的时机,当线程池处理不了过多的任务时触发

 举例说明:

5.1.1拒绝策略

拒绝策略有4中,根据自己的业务场景选择合适的拒绝策略即可。

5.2线程池的工作原理

这七个参数搭配使用:

1.当任务添加到线程池中时,先判断任务数是否大于核心线程数

2.如果不大于直接执行,否则加入阻塞队列

3.当阻塞队列满了之后,会按指定的线程最大数创建临时线程

4.当阻塞队列满了,而且临时线程也创建完成,再提交任务时,执行拒绝策略

5.当任务减少,临时线程达到空闲时长时,会被回收

5.3为什么不适用系统自带的线程池

 

 

补充:工厂模式

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。

先来看看一个代码示例:

定义一个Student类,定义有参构造

由于重载过程,参数列表相同而报错 。

使用工厂方法:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值