Skip to content

Latest commit

 

History

History
223 lines (189 loc) · 6.82 KB

线程池.md

File metadata and controls

223 lines (189 loc) · 6.82 KB

线程池

使用线程池的好处

  1. 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源, 还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用 线程池,必须对其实现原理了如指掌。

new Thread弊端

  • 每次new Thread,新建对象,性能差

  • 线程缺乏统一管理,可能无限制的新建线程,相互竞争, 有可能占用过多下同资源导致司机或OOM

  • 缺少更多功能,如更多执行、定期执行、线程中断

线程池的好处

  • 重用存在的线程没减少对象创建、消亡的开销,性能差

  • 可有效控制最大并发线程数,提高系统资源利用率, 同时可以避免过多资源竞争,避免阻塞

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

ThreadPoolExecutor

  • 构造方法参数
构造方法的参数 解释
CorePoolSize 核心线程数量,线程池的基本大小。
WorkQueue 任务队列,用于保存等待执行的任务的阻塞队列,有ArrayBlockingQueue,LinkedBlockingQueue,SychronousQueue,PriorityQueue
MaximumPoolSize 最大线程数
KeepAliveTime 线程没有任务执行时最多保持多久时间终止
Unit keepAliveTime的事件单位
Threadfactory 线程工厂,用来创建线程,可以给创建的线程设置一个有意义的名字。
RejectHandler 饱和策略,当拒绝处理任务时的策略
  • 线程池实例的几种状态
  • 常用方法:
方法 解释
execute() 用于提交不需要返回值的任务
submit() 用于提交需要返回值的任务,会返回一个Future类型的对象
shutdown() 关闭线程池,等到任务都执行完
shutdownNow() 关闭线程池,不等到任务都执行完
getTaskCount() 线程池已执行和未执行的任务总数
getCompletedTaskCount() 已完成的任务数量
getPoolSize() 线程池当前的线程数量
getActiveCount() 当前线程池正在执行任务的线程数量

Executor框架接口

线程池类图

4种线程池

  • Executors.newCachedThreadPool()

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

public class ThreadPoolExample1 {
    public static void main(String[] args) {
        ExecutorService executorService= Executors.newCachedThreadPool();
        for(int i=0;i<10;i++){
            final int index=i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("task:{"+index+"}");
                }
            });
        }
        executorService.shutdown();
    }
}
/**
 * 输出结果:
 task:{0}
 task:{1}
 task:{2}
 task:{3}
 task:{4}
 task:{5}
 task:{6}
 task:{8}
 task:{9}
 task:{7}
 */
  • Executors.newFixedThreadPool(int)

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

public class ThreadPoolExample2 {
    public static void main(String[] args) {
        ExecutorService executorService= Executors.newFixedThreadPool(3);
        for(int i=0;i<10;i++){
            final int index=i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("task:{"+index+"}");
                }
            });
        }
        executorService.shutdown();
    }
}
/**
 * 输出结果:每隔1s输出一组(因为线程池大小为3,每个任务输出index后sleep 1秒,所以每隔1秒打印3个数字。)
 task:{0}
 task:{2}
 task:{1}

 task:{4}
 task:{5}
 task:{3}

 task:{8}
 task:{7}
 task:{6}

 task:{9}
 */
  • Executors.newSingleThreadExecutor()

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

public class ThreadPoolExample3 {
    public static void main(String[] args) {
        ExecutorService executorService= Executors.newSingleThreadExecutor();
        for(int i=0;i<10;i++){
            final int index=i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("task:{"+index+"}");
                }
            });
        }
        executorService.shutdown();
    }
}
/**
 * 输出结果:结果依次输出,相当于顺序执行各个任务。
 task:{0}
 task:{1}
 task:{2}
 task:{3}
 task:{4}
 task:{5}
 task:{6}
 task:{7}
 task:{8}
 task:{9}
 */
  • Executors.newScheduledThreadPool(int)

创建一个定长线程池,支持定时及周期性任务执行。

public class ThreadPoolExample4 {
    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

        //延迟11s执行
       /*executorService.schedule(new Runnable() {
           @Override
           public void run() {
               System.out.println("schedule rum");
           }
       },11, TimeUnit.SECONDS);
       executorService.shutdown();*/

       //延迟1秒后每3秒执行一次
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("schedule rum");
            }
        },1,3,TimeUnit.SECONDS);

       //每隔5s执行
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("timer run");
            }
        }, new Date(), 5 * 1000);

    }
}
/**
 * 表示延迟1秒后每3秒执行一次。
 * ScheduledExecutorService比Timer更安全,功能更强大。
 */