栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java线程池的理解与实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java线程池的理解与实现

文章目录

基本原理使用Executors创建线程池

使用步骤代码实现创建指定线程数量 使用ThreadPoolExecutor创建线程池

参数详解代码实现: 任务拒绝策略

1、默认淘汰策略AbortPolicy()2、ThreadPoolExecutor.DiscardPolicy3、ThreadPoolExecutor.DiscardOldestPolicy4、ThreadPoolExecutor.CallerRunsPolicy

基本原理

和j2ee的连接池技术很像,都属于池化技术。在手写多个线程的过程中,经常会new好几个thread对象,也就是为线程对象申请资源,然后在线程运行完相应的代码后再释放资源
这一过程只有两三个还好,而当高并发的情形下,很有可能有几百上千个线程需要频繁的创建、销毁。这就导致了非常严重的系统资源浪费。
于是线程池技术应运而生,有一个容器一开始就装了很多的线程,需要用的时候从容器中拿出来,不需要的时候再放回容器,这样就避免了频繁申请资源,销毁线程而导致的资源浪费,这个容器就是线程池

使用Executors创建线程池 使用步骤


注意:线程池在创建之初默认是空的,默认能容纳int类型的最大值个线程

代码实现
public class MyThreadPool {
    public static void main(String[] args) throws InterruptedException {
        
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(()->{
            System.out.println(Thread.currentThread().getName() + " is running...");
        });
        Thread.sleep(2000);
        executorService.submit(()->{
            System.out.println(Thread.currentThread().getName() + " is running...");
        });
        executorService.shutdown();
    }
}


一些说明:
1、当前版本会让Executors.newCachedThreadPool()报红
原因是使用Executors创建线程池不会传入这个参数而使用默认值所以我们常常忽略这一参数,而且默认使用的参数会导致资源浪费,不可取。

2、为什么运行结果是2个相同的线程
因为在线程池中一个线程使用完后会自动归还到线程池中,当代码中

executorService.submit(()->{
	System.out.println(Thread.currentThread().getName() + " is running...");
});

执行完后,线程就应该归还给线程池,而这一个动作需要一定的时间,于是我们的sleep方法覆盖了这一时间,当再次执行这段代码块的时候,就会从线程中再取一个,此时线程1已经回到了池中,所以第二次执行时,仍然使用线程1

创建指定线程数量

使用Executors.newFixedThreadPoll()方法
这个方法默认创建的也是控线程池,但是可以在参数中指定线程个数的上限

使用ThreadPoolExecutor创建线程池

该实现方法的参数较为复杂,因此我们用一个实际的场景帮助理解

背景:某餐厅有服务员,分为正式员工和临时员工。当顾客特别多的时候,会招聘临时服务员,当顾客较少,等待一段时间之后(确保顾客不会增多了),解雇聘临时服务员,只有正式员工(万恶的资本家)。
我们抽象出如下核心元素——

参数详解

根据这些抽象元素,我们具体化为参数
参数一:核心线程数量
参数二:最大线程数
参数三:空闲线程最大存活时间
参数四:时间单位 — TimeUnit
参数五:任务队列 — 让任务在队列中等着,等有线程空闲了,再从这个队列中获取任务并执行。
参数六:创建线程工厂 — 按照默认的方式创建线程对象.
参数七:任务的拒绝策略

代码实现:

先看看这个类构造方法的的源码,该构造方法有七个参数,分别是上述三个参数

public class MyThreadPoolExecutor {
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                2,
                5,
                2,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        pool.shutdown();
    }
}
任务拒绝策略 1、默认淘汰策略AbortPolicy()

上述代码中AbortPolicy()是默认的淘汰策略,表示任务数量超过最大线程数(线程池+等待队列)即丢弃多余的任务。

注意:该方法在丢弃任务后会抛出RejectedExecutionException异常。

2、ThreadPoolExecutor.DiscardPolicy

特征:丢弃任务,但是不抛出异常这是不推荐的做法。

3、ThreadPoolExecutor.DiscardOldestPolicy

关键在于“oldest”
特征:抛弃队列中等待最久的任务然后把当前任务加入队列中。

4、ThreadPoolExecutor.CallerRunsPolicy

特征:调用任务的run方法绕过线程池直接执行
实现的策略是,当当前线程池无法分配足够的线程执行任务时,将把多余的任务交给别的线程完成

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770254.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号