线程池的创建与执行

目录

一、线程池

1.概念

2.线程池的常用类和接口

3.线程池的常见使用方法

二、线程池的优点

三、线程池的执行流程和配置参数

 四、线程池的状态

线程池使用注意事项:


一、线程池

1.概念

        线程池其实就是一中多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线程后自动启动这些任务。这里的线程就是我们前面学过的线程,这里的任务就是我们前面学过的实现了RunnableCallable接口的实例对象。

2.线程池的常用类和接口

        在Java标准库提供了如下几个类或接口,来操作并使用线程池:
1.ExecutorService接口:进行线程池的操作访问;
2.Executors类:创建线程池的工具类;
3.ThreadPoolExecutor及其子类:封装线程池的核心参数和运行机制。

       线程池的基本使用可见线程创建方式4.

3.线程池的常见使用方法

● 执行无返回值的线程任务:void execute(Runnable command);
● 提交有返回值的线程任务:Future<T> submit(Callable<T> task);
● 关闭线程池:void shutdown(); 或 shutdownNow();
● 等待线程池关闭:boolean awaitTermination(long timeout, TimeUnit unit);

        执行线程任务:
        execute()只能提交Runnable类型的任务,没有返回值,而submit()既能提交Runnable类型任务也能提交Callable类型任务,可以返回Future类型结果,用于获取线程任务执行结果。
        execute()方法提交的任务是直接抛出异常,而submit()方法是捕获异常,当调用Future的get()方法获取返回值时,才会抛出异常。

        关闭线程池:
        线程池在程序结束的时候要关闭。shutDown()方法会等执行完任务然后再关闭。shutdownNow()会立刻停止正在执行的任务并且关闭;
        当使用awaitTermination(timeout,TimeUnit)方法时,主线程会处于一种等待的状态,按照指定的timeout检查线程池。一般用来判断线程池是否关闭,配合while使用。

二、线程池的优点

1、重用存在的线程,减少对象创建销毁的开销。

2、可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞

争,避免堵塞。

3、提供定时执行、定期执行、单线程、并发数控制等功能。

三、线程池的执行流程和配置参数

执行流程:

1. 提交一个新线程任务,线程池会在线程池中分配一个空闲线程,用于执行线程任务;

2. 如果线程池中不存在空闲线程,则线程池会判断当前“存活的线程数”是否小于核心线程数corePoolSize。
① 如果小于核心线程数corePoolSize,线程池会创建一个新线程(核心线程)去处理新线程任务; 如果大于核心线程数corePoolSize,线程池会检查工作队列
② 如果工作队列未满,则将该线程任务放入工作队列进行等待。线程池中如果出现空闲线程,将从工作队列中按照FIFO的规则取出1个线程任务并分配执行; 如果工作队列已满,则判断线程数是否达到最大线程数maximumPoolSize;
③ 如果当前“存活线程数”没有达到最大线程数maximumPoolSize,则创建一个新线 程(非核心线程)执行新线程任务;
    如果当前“存活线程数”已经达到最大线程数maximumPoolSize,直接采用拒绝策 略处理新线程任务;
        

        综上所述,执行顺序为:空闲线程——>核心线程——>工作队列——>最大线程数——>拒绝策略

image.png

配置参数:        

参数描述
int corePoolSize核心线程池的大小(创建后会不被回收)
int maximumPoolSize线程池最大线程数
long keepAliveTime超时时间:可被回收的线程的空闲时间大于该值会被回收
TimeUnit unit超时单位

BlockingQueue<Runnable> workQueue

阻塞队列:存储等待执行的任务
ThreadFactory threadFactory用于创建线程,以及自定义线程名称,需要实现ThreadFactory接口
RejectedExecutorHandler handler拒绝策略:当线程池内的线程耗尽,并且工作队列达到已满时,新提交的任务,将使用拒绝策略进行处理

代码如下:

自定义线程池:

//自定义线程池(自定义线程工厂)
public class Demo4 {
    public static void main(String[] args) {
        //参数1:线程池核心线程数
        //参数2:线程池最大线程数
        //参数3:非核心线程存活时间
        //参数4:时间单位
        //参数5:阻塞工作队列
        //参数6:线程工厂
        ExecutorService executorService = new ThreadPoolExecutor(10,11,1, TimeUnit.SECONDS,new LinkedBlockingDeque<>(),new MyThreadFactory());

        for (int i = 0;i < 11;i++) {
            executorService.execute(new Task1("订单" + i));
        }

        executorService.shutdown();
    }
}
//实现类
class Task1 implements Runnable{
    private String name;
    public Task1(String name){
        this.name = name;

    }
    @Override
    public void run() {
        System.out.println("启动线程——>" + this.name + "(" + LocalDateTime.now() + ")");

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("关闭线程<——" + this.name + "(" + LocalDateTime.now() + ")");
    }
}

自定义线程工厂:

//自定义线程工厂
public class MyThreadFactory implements ThreadFactory {
    private final AtomicInteger number = new AtomicInteger(0);
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setName("线程:" + number.incrementAndGet());
        return t;
    }

}

四、线程池的状态

        线程池的状态:

· RUNNING:运行状态,线程池一旦被创建,就会处于RUNNING状态,并且线程池中的任务数为0.该状态的线程池会接受新任务,并处理工作队列中的任务。

· SHUTDOWN:关闭状态,调用shutdown()方法可以切换到该状态,该状态的线程池不会接收新任务,但会处理工作队列中的任务;

· STOP:停止状态,调用shutdownNow()方法可以切换到该状态,该状态不会接收新任务,也不会处理阻塞队列中的任务,而且会中断正在运行的任务;

· TIDYING整理状态,该状态表明所有的任务已经运行终止,记录的任务数量为0;

· TERMINATED:终止状态,该状态表示线程池彻底关闭。

线程池状态.webp

线程池使用注意事项:

        在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建,一方面是使线程的创建更加规范合理开辟线程数量;另一方面将线程的细节管理交给线程池处理,优化了资源的开销。因为newFixedThreadPool()、newSingleThreadExecutor()、NewCachedTheadPool()等方法有局限性,不够灵活;应使用ThreadPoolExecutor有助于明确线程池的运行规则,创建符合自己业务场景需要的线程池,避免资源耗尽的风险,同时应避免线程使用默认名称。

在安卓中,线程池创建和销毁是为了解决以下问题。首先,创建和销毁线程会带来性能开销,特别是在频繁进行耗时操作时。如果每次都创建和销毁线程,会消耗大量的系统资源。而线程池可以复用线程,避免了频繁创建和销毁线程所带来的性能开销。\[2\] 其次,当大量的线程同时运行时,可能会导致资源紧张,因为线程底层的机制是切分CPU的时间。如果大量的线程同时存在,它们会互相抢占系统资源,导致阻塞现象的发生。而线程池可以有效地控制线程的最大并发数,避免了大量线程之间互相抢占资源的问题。\[2\] 因此,线程池创建和销毁在安卓中是为了提高性能和资源利用率。通过复用线程和控制最大并发数,线程池可以有效地管理线程,并提供定时执行和循环执行等功能。\[2\] #### 引用[.reference_title] - *1* [Android与线程池](https://blog.csdn.net/qq_39969226/article/details/88141264)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Android 线程池★](https://blog.csdn.net/zenmela2011/article/details/120968129)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

起个有趣的名字好难

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值