线程池ThreadPoolExecutor

线程池是一种多线程处理形式,预先创建好多个线程放入池中,减少创建和销毁线程的开销。本文介绍了线程池的概念、好处,以及四种类型的线程池创建方式,并通过示例展示了如何执行Runnable和Callable任务。线程池参数如corePoolSize、maximumPoolSize等控制线程管理,并讨论了拒绝策略。
  • 什么是线程池(类似于共享单车
    • 创建和销毁对象是非常耗费时间的
    • 创建对象:需要分配内存等资源
    • 销毁对象:虽然不需要程序员操心,但是垃圾回收器会在后台一直跟踪并销毁
    • 对于经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大
    • 思路:创建好多个线程,放入线程池中,使用时直接获取引用,不使用时放回池中。可以避免频繁创建销毁、实现重复利用
    • 生活案例:借用和归还电脑,共享单车
    • 技术案例:线程池、数据库连接池
    • JDK1.5起,提供了内置线程池 
  • 线程池的好处
    • 提高响应速度(减少了创建新线程的时间)
    • 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
    • 提高线程的可管理性:避免线程无限制创建、从而销耗系统资源,降低系统稳定性,甚至内存溢出或者CPU耗尽
  • 线程池的应用场合
    • 需要大量线程,并且完成任务的时间短
    • 对性能要求苛刻
    • 接受突发性的大量请求

1.使用线程池执行大量的Runnable命令

 

//创建一个线程池:不同的线程池

ExecutorService pool1 = Executors.newSingleThreadExecutor();//创建一个线程池,池中只有1个线程,保证线程一直存在

ExecutorService pool2 = Executors.newFixedThreadPool(10);  //创建一个线程池,池中有固定数量的线程

ExecutorService pool3 = Executors.newCachedThreadPool();//线程池中线程的数量可以动态变化:0~MAX_VALUE,来几个线程线程池开几个

ExecutorService pool4 = Executors.newScheduledThreadPool(10);//定时任务,用来执行大量的定时任务


//使用线程池执行大量的Runnable任务
for (int i = 0; i < 20; i++) {
    myrunnable a = new myrunnable(i);
    //new Thread(a).start();
    //pool1.execute(a);
    pool2.execute(a);

}

//关闭线程池
pool1.shutdown();
pool2.shutdown();
pool3.shutdown();
pool4.shutdown();

2.使用线程池执行大量的Callable任务

//创建一个线程池

ExecutorService pool1 = Executors.newSingleThreadExecutor();//创建一个线程池,池中只有1个线程,保证线程一直存在

ExecutorService pool2 = Executors.newFixedThreadPool(10);  //创建一个线程池,池中有固定数量的线程

ExecutorService pool3 = Executors.newCachedThreadPool();//线程池中线程的数量可以动态变化:0~MAX_VALUE,来几个线程线程池开几个

ExecutorService pool4 = Executors.newScheduledThreadPool(10);//定时任务,用来执行大量的定时任务


//使用线程池执行大量的Runnable任务
for (int i = 0; i < 20; i++) {
    int finalI = i;
    Callable<Integer> a = new Callable<Integer>() {//匿名内部类定义Callable接口
       @Override
       public Integer call() throws Exception {
           int result = new Random().nextInt(10);

           System.out.println("线程"+ finalI +"开始");
            Thread.sleep(3000);
           System.out.println("线程"+ finalI +"结束");

           return result;
       }
   } ;

    FutureTask<Integer> task = new FutureTask(a);//借助Futuretask实现callable接口
    pool2.submit(task);//用线程池启动线程
    int result = task.get();//利用Futuretask的get方法获取返回值
    System.out.println(result);
}


//关闭线程池
pool1.shutdown();
pool2.shutdown();
pool3.shutdown();
pool4.shutdown();

3.线程池API

  1. Executor:线程池顶级接口,只有一个方法
  2. ExecutorService:真正的线程池接口
    1. void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行Runnable
    2. <T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般用来执行Callable
    3. void shutdown() :关闭线程池
  3. AbstractExecutorService:基本实现了ExecutorService的所有方法
  4. ThreadPoolExecutor:默认的线程池实现类
  5. ScheduledThreadPoolExecutor:实现周期性任务调度的线程池
  6. Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池
    1. Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池
    2. Executors.newFixedThreadPool(n);  创建一个可重用固定线程数的线程池
    3. Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池
    4. Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

  1. 线程池ThreadPoolExecutor参数 

public ThreadPoolExecutor(int corePoolSize,

          int maximumPoolSize,

          long keepAliveTime,

          TimeUnit unit,

          BlockingQueue<Runnable> workQueue,

          ThreadFactory threadFactory,

          RejectedExecutionHandler handler) {

}

    • corePoolSize:核心池的大小
      • 默认情况下,创建了线程池后,线程数为0,当有任务来之后,就会创建一个线程去执行任务。
      • 但是当线程池中线程数量达到corePoolSize,就会把到达的任务放到队列中等待。
    • maximumPoolSize:最大线程数。
      • corePoolSizemaximumPoolSize之间的线程数会自动释放,小于等于corePoolSize的不会释放。当大于了这个值就会将任务由一个丢弃处理机制来处理。
    • keepAliveTime:线程没有任务时最多保持多长时间后会终止
      • 默认只限于corePoolSizemaximumPoolSize间的线程
    • TimeUnit
      • keepAliveTime的时间单位
    • BlockingQueue
      • 存储等待执行的任务的阻塞队列,有多种选择,可以是顺序队列、链式队列等。
    • ThreadFactory
      • 线程工厂,默认是DefaultThreadFactoryExecutors的静态内部类
    • RejectedExecutionHandler
      • 拒绝处理任务时的策略。如果线程池的线程已经饱和,并且任务队列也已满,对新的任务应该采取什么策略。
      • 比如抛出异常、直接舍弃、丢弃队列中最旧任务等,默认是直接抛出异常。

1CallerRunsPolicy:如果发现线程池还在运行,就直接运行这个线程

2DiscardOldestPolicy:在线程池的等待队列中,将头取出一个抛弃,然后将当前线程放进去。

3DiscardPolicy:什么也不做

4AbortPolicyjava默认,抛出一个异常:

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值