线程池的创建和使用

概述
  • 线程池就比如是一个装线程的池子,里面存在很大创建时就创建好的线程
  • 创建的线程池要手动关闭,否则线程池里面的线程一直处于空闲,等待任务
  • 线程池在启动的时,会创建大量空闲线程,当我们向线程池提交任务的时,线程池就会启动一个线程来执行该任务。等待任务执行完毕以后,线程并不会死亡,而是再次返回到线程池中称为空闲状态。等待下一次任务的执行。
创建线程池的方式
一、用Executors类的静态方法
  • static ExecutorService newCachedThreadPool() :创建一个默认的线程池,默认为认最多可以容纳int类型的最大值。
  • 注意:创建一个线程池,根据需要创建新线程,但在可用时将重用先前构造的线程。 这些池通常会提高执行许多短期异步任务的程序的性能。 如果可用,调用execute将重用先前构造的线程。 如果没有可用的现有线程,则会创建一个新线程并将其添加到池中。 60 秒内未使用的线程将被终止并从缓存中删除。 因此,保持空闲足够长时间的池不会消耗任何资源。
  • static newFixedThreadPool(int nThreads) 创建一个指定最多线程数量的线程池
  • 注意:创建一个线程池,该线程池重用固定数量的线程在共享的无界队列中运行。 在任何时候,最多nThreads线程将是活动的处理任务。 如果在所有线程都处于活动状态时提交了其他任务,它们将在队列中等待,直到有线程可用。 如果任何线程在关闭前的执行过程中因失败而终止,则在需要执行后续任务时,将有一个新线程取代它。 池中的线程将一直存在,直到它被明确shutdown
  • 代码示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) throws InterruptedException {
		 //1.创建默认数量的线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(()->{
            System.out.println("线程1");
        });
        executorService.submit(() -> {
            System.out.println("线程2");
        });
        //关闭线程池
        executorService.shutdown();
        //2.创建指定上限的线程池
        ExecutorService executorService2 = Executors.newFixedThreadPool(2);
        ThreadPoolExecutor pool = (ThreadPoolExecutor) executorService2;
        //返回池中的当前线程数
        System.out.println("当前线程数"+pool.getPoolSize());
        executorService2.submit(() -> {
            System.out.println("线程a");
        });
        executorService2.submit(() -> {
            System.out.println("线程b");
        });
        executorService2.submit(() -> {
            System.out.println("线程c");
        });
        System.out.println("当前线程数"+pool.getPoolSize());
        //关闭线程池
        executorService2.shutdown();
	}
}
  • 结果
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/ac198931b9aa4257a370dcece737ccdf.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5aSn6LC3b3Zv,size_20,color_FFFFFF,t_70,g_se,x_16
二、new ThreadPoolExecutor()创建线程池对象
  • ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);
  • 其构造方法:public ThreadPoolExecutor(int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler)
  • 使用给定的初始参数创建一个新的ThreadPoolExecutor 。
    • 参数:
    • corePoolSize – 要保留在池中的线​​程数,即使它们处于空闲状态,除非设置了allowCoreThreadTimeOut
    • maximumPoolSize – 池中允许的最大线程数
    • keepAliveTime – 当线程数大于核心数时,这是多余空闲线程在终止前等待新任务的最长时间。
    • unit – keepAliveTime参数的时间单位
    • workQueue – 用于在执行任务之前保存任务的队列。 这个队列将只保存execute方法提交的Runnable任务。
    • threadFactory – 执行程序创建新线程时使用的工厂
    • handler – 执行被阻塞时使用的处理程序,因为达到了线程边界和队列容量,有四个子类
1. ThreadPoolExecutor.AbortPolicy:    丢弃任务并抛出RejectedExecutionException异常。是默认的策略。
2. ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常 这是不推荐的做法。
3. ThreadPoolExecutor.DiscardOldestPolicy:  抛弃队列中等待最久的任务 然后把当前任务加入队列中。
4. ThreadPoolExecutor.CallerRunsPolicy:    调用任务的run()方法绕过线程池直接执行。
  • 注意:线程池对多可执行的任务数 = 队列容量 + 最大线程数
  • 代码
import java.util.concurrent.*;
public class Test {
    public static void main(String[] args) throws InterruptedException {
			ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1 , 3 , 20 ,
                TimeUnit.SECONDS ,
                new ArrayBlockingQueue<>(1) , Executors.defaultThreadFactory() , new
                ThreadPoolExecutor.AbortPolicy()) ;
// 提交5个任务,而该线程池最多可以处理4个任务,当我们使用AbortPolicy这个任务处理策略的时候,就会抛出异常
        for(int x = 0 ; x < 5 ; x++) {
            threadPoolExecutor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + "---->> 执行了任务");
            });
            //停止1s则会每个任务正常,因为任务完成了不占用里面的线程‘
            //Thread.sleep(1000);
        }
	}
}
  • 结果
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值