• 线程池[重点]


    线程池概述

    线程池就是一个可以复用线程的技术。

    不使用线程池的问题 :如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。

    线程池实现的API、参数说明

    JDK 5.0起提供了代表线程池的接口:ExecutorService。

    如何得到线程池对象:

    方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

    方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。

    ThreadPoolExecutor构造器的参数说明: 

    1. public ThreadPoolExecutor(int corePoolSize,
    2. int maximumPoolSize,
    3. long keepAliveTime,
    4. TimeUnit unit,
    5. BlockingQueue workQueue,
    6. ThreadFactory threadFactory,
    7. RejectedExecutionHandler handler)

    线程池常见面试题:

    临时线程什么时候创建啊?

    新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

    什么时候会开始拒绝任务?

    核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。 

    ThreadPoolExecutor创建线程池对象示例

    1. ExecutorService pools = new ThreadPoolExecutor(3, 5
    2. , 8 , TimeUnit.SECONDS, new ArrayBlockingQueue<>(6),
    3. Executors.defaultThreadFactory() , new ThreadPoolExecutor.AbortPolicy());

    ExecutorService的常用方法

    新任务拒绝策略

    线程池处理Runnable任务

    1. public class MyRunnable implements Runnable{
    2. @Override
    3. public void run() {
    4. for (int i = 0; i < 5; i++) {
    5. System.out.println(Thread.currentThread().getName() + "输出了:HelloWorld ==> " + i);
    6. }
    7. try {
    8. System.out.println(Thread.currentThread().getName() + "本任务与线程绑定了,线程进入休眠了~~~");
    9. Thread.sleep(10000000);
    10. } catch (Exception e) {
    11. e.printStackTrace();
    12. }
    13. }
    14. }
    1. public class ThreadPoolDemo1 {
    2. public static void main(String[] args) {
    3. // 1、创建线程池对象
    4. /**
    5. public ThreadPoolExecutor(int corePoolSize,
    6. int maximumPoolSize,
    7. long keepAliveTime,
    8. TimeUnit unit,
    9. BlockingQueue workQueue,
    10. ThreadFactory threadFactory,
    11. RejectedExecutionHandler handler)
    12. */
    13. ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
    14. 6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
    15. new ThreadPoolExecutor.AbortPolicy() );
    16. // 2、给任务线程池处理。
    17. Runnable target = new MyRunnable();
    18. pool.execute(target);
    19. pool.execute(target);
    20. pool.execute(target);
    21. pool.execute(target);
    22. pool.execute(target);
    23. pool.execute(target);
    24. pool.execute(target);
    25. pool.execute(target);
    26. // 创建临时线程
    27. pool.execute(target);
    28. pool.execute(target);
    29. // // 不创建,拒绝策略被触发!!!
    30. // pool.execute(target);
    31. // 关闭线程池(开发中一般不会使用)。
    32. // pool.shutdownNow(); // 立即关闭,即使任务没有完成,会丢失任务的!
    33. pool.shutdown(); // 会等待全部任务执行完毕之后再关闭(建议使用的)
    34. }
    35. }

    线程池处理Callable任务

    1. /**
    2. 1、定义一个任务类 实现Callable接口 应该申明线程任务执行完毕后的结果的数据类型
    3. */
    4. public class MyCallable implements Callable{
    5. private int n;
    6. public MyCallable(int n) {
    7. this.n = n;
    8. }
    9. /**
    10. 2、重写call方法(任务方法)
    11. */
    12. @Override
    13. public String call() throws Exception {
    14. int sum = 0;
    15. for (int i = 1; i <= n ; i++) {
    16. sum += i;
    17. }
    18. return Thread.currentThread().getName()
    19. + "执行 1-" + n+ "的和,结果是:" + sum;
    20. }
    21. }
    1. public class ThreadPoolDemo2 {
    2. public static void main(String[] args) throws Exception {
    3. // 1、创建线程池对象
    4. /**
    5. public ThreadPoolExecutor(int corePoolSize,
    6. int maximumPoolSize,
    7. long keepAliveTime,
    8. TimeUnit unit,
    9. BlockingQueue workQueue,
    10. ThreadFactory threadFactory,
    11. RejectedExecutionHandler handler)
    12. */
    13. ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
    14. 6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
    15. new ThreadPoolExecutor.AbortPolicy() );
    16. // 2、给任务线程池处理。
    17. Future f1 = pool.submit(new MyCallable(100));
    18. Future f2 = pool.submit(new MyCallable(200));
    19. Future f3 = pool.submit(new MyCallable(300));
    20. Future f4 = pool.submit(new MyCallable(400));
    21. Future f5 = pool.submit(new MyCallable(500));
    22. // String rs = f1.get();
    23. // System.out.println(rs);
    24. System.out.println(f1.get());
    25. System.out.println(f2.get());
    26. System.out.println(f3.get());
    27. System.out.println(f4.get());
    28. System.out.println(f5.get());
    29. }
    30. }

    Executors工具类实现线程池

    Executors:线程池的工具类通过调用方法返回不同类型的线程池对象。

    api

    注意:Executors的底层其实也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。

    Executors使用可能存在的陷阱

    大型并发系统环境中使用Executors如果不注意可能会出现系统风险。

     

  • 相关阅读:
    使用Spring来管理对象关系映射(ORM)
    Oracle工程师离职并回踩:MySQL糟糕透顶,强烈推荐PostgreSQL
    网络安全(黑客技术)2024年三个月自学手册
    SQL必会——常见时间数据的处理
    三菱FX5U系列PLC内置高速计数器的使用方法示例
    【分类-SVDD】基于支持向量数据描述 (SVDD) 的多类分类算法附matlab代码
    去掉实体类String类型字段的值前后空格
    SSM+基于SSM的课堂考勤管理系统的设计与实现 毕业设计-附源码191617
    高通USER版本不支持fastboot升级
    flink cdc MySQL2Doris 案例分享
  • 原文地址:https://blog.csdn.net/daqi1983/article/details/134511379