`
y806839048
  • 浏览: 1126437 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

线程池归纳

阅读更多

总括:

 

线程池中的线程创建线程池的时候没有创建,只有在具体执行任务的时候,才检查是否达到核心线程数,没有就创建---类似延时加载

核心线程消耗不了就放入队列,之后新进入的任务放入队列,线程执行任务优先从队列获取

队列满了之后,核心线程还是消费不过来,启用最大线程数,一旦启用最大线程数,直到队列没有积压任务,非核心线程空闲超时自动回收最后留下核心线程数--新创建核心线程外的线程数

多线程的3中方法就是创建线程任务的方法,线程任务放入线程中执行

线程池中的start,最终调用的还是任务中的run方法

线程池源码中worker相当于thread,任务队列中的队列相当于任务run方法

线程池执行线程的时候抛异常时就会删除旧的线程,重新建立新的线程

 

FixedThreadPool 中的变量即使核心线程数,也是最大线程数

 

 public static ExecutorService newFixedThreadPool(int nThreads) {

        return new ThreadPoolExecutor(nThreads, nThreads,

                                      0L, TimeUnit.MILLISECONDS,

                                      new LinkedBlockingQueue<Runnable>());

    }

 

 

 

 

带着几个问题进入源码分析:

1. 线程池是什么时候创建线程的?

2. 任务runnable task是先放到core到maxThread之间的线程,还是先放到队列?

3. 队列中的任务是什么时候取出来的?

4. 什么时候会触发reject策略?

5. core到maxThread之间的线程什么时候会die?

6. task抛出异常,线程池中这个work thread还能运行其他任务吗?

 

先写一段基础代码,进入分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static void main(String[] args) {
 
        ExecutorService executorService = new ThreadPoolExecutor(250, TimeUnit.DAYS,
                new ArrayBlockingQueue<>(1), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
//                thread.setDaemon(true);
                return thread;
            }
        });
        // 对象创建后,线程实际还没开始创建
 
        // 执行execute时,检查当前池中线程数大小是否小于core number, 如果是,则创建新线程
        executorService.execute(() -> {
            System.out.println("任务1@" + Thread.currentThread().getName());
            sleepTime();
            System.out.println(1);
        });
 
        //检查当前池中线程数大小是否小于core number, 如果是,则创建新线程
        executorService.execute(() -> {
            System.out.println("任务2@" + Thread.currentThread().getName());
            sleepTime();
            System.out.println(2);
        });
 
        // 检查当前池中线程数大小是否小于core number, 如果不是,则偿试放入队列
        // 这个任务是加到队列去的, 注意队列大小只有1,
        // TODO 队列中的任务是什么时候取出来的?   任务1或者2结束后所占用的线程 会运行队列中的任务,这个任务是在最后才运行,比4运行的还晚
        executorService.execute(() -> {
            System.out.println("任务3@" + Thread.currentThread().getName());
            sleepTime();
            System.out.println(3);
        });
 
        // 检查当前池中线程数大小是否小于core number, 如果不是,则偿试放入队列,放入队列也失败,则增加新的worker线程
        // 这个任务是加到core以外的新线程去的
        executorService.execute(() -> {
            System.out.println("任务4@" + Thread.currentThread().getName());
            sleepTime();
            System.out.println(4);
        });
    }

  

注意第3行,创建一个核心池2, 最大池5, 队列为1的线程池

至少在new ThreadPoolExecutor()时,Thread对象并没有初始化. 这里仅仅指定了几个初始参数

 

执行第一个execute时,进入调试jdk源码

 代码块1

第一个if, 判断如果当前线程数小于corePoolSize, 则创建新的核心worker对象(Worker中指向Thread对象,保持引用,保证不会被GC回收)

     我们的示例代码中,第1和第2个任务都是这样创建出线程的

第二个if,   判断如果当前线程数大于corePoolSize, 并偿试放入队列 workQueue.offer(command) 放入成功后等待线程池调度【见后面的getTask()】

     示例代码中,第3个任务是这样等待调度的,最后才执行

第三个if,  偿试放入队列 workQueue.offer(command) 失败, 增加一个非core的线程

     示例代码中,第4个任务是这样开始的

 

 

然后再看addWorker()的过程

 

new Worker构造和线程启动

线程启动后,又做了哪些工作:

异常分析

没抛异常时,此线程会一直在while(task !=null || (task = getTask())!=null)中跑

那么有异常时,再看一下processWorkerExit

 

可以 看出,有异常时 旧的worker会被删除(GC回收),再创建新的Worker, 即有异常时 旧worker不可能再执行新的任务

 

 

总结:

 

Q. 线程池是什么时候创建线程的?

A.任务提交的时候

Q.任务runnable task是先放到core到maxThread之间的线程,还是先放到队列?

A.先放队列!!!

Q. 队列中的任务是什么时候取出来的?

A. worker中 runWorker() 一个任务完成后,会取下一个任务

Q. 什么时候会触发reject策略?

A.队列满并且maxthread也满了, 还有新任务,默认策略是reject

Q. core到maxThread之间的线程什么时候会die?

A.  没有任务时,或者抛异常时。   

   core线程也会die的,core到maxThread之间的线程有可能会晋升到core线程区间,

   core max只是个计数,线程并不是创建后就固定在一个区间了

Q. task抛出异常,线程池中这个work thread还能运行其他任务吗?

A. 不能。 但是会创建新的线程, 新线程可以运行其他task。

对于 schedulerThreadPoolExecutor?   虽然有新线程,但是旧的循环任务不会再继续执行了, 开发实践推荐任务中捕获所有Exception

 

分享到:
评论

相关推荐

    Net线程的一些问题和误解[归纳].pdf

    创建线程有多种方式,包括直接使用`Thread`类、通过委托`Delegate.BeginInvoke`以及使用线程池`ThreadPool.QueueUserWorkItem`。 1. **使用Thread类**:通过实例化`Thread`对象并指定`ThreadStart`或`...

    NET线程详解[归纳].pdf

    线程池是一种优化线程管理的机制,它维护着一组可重用的线程,当需要新线程时,可以从线程池中获取而不是每次都创建新的。每个进程都有自己的线程池,而不是全局共享。手动设置线程池的最大值可能会导致资源浪费或...

    Weblogic性能调优[归纳].pdf

    在《Weblogic性能调优[归纳].pdf》中,作者李先林分享了一系列关于如何针对Weblogic应用服务器进行性能优化的经验与方法。这对于那些在实际项目中遇到性能瓶颈的专业人士来说,是非常宝贵的资源。 #### 二、JVM调整...

    东北大学软件学院程序实践三 网络应用程序设计

    6. 总结与反思:总结实验收获,对所学知识进行归纳,提出对未来学习或工作的启示。 通过这次实践,学生们不仅能深入理解网络应用程序设计的核心技术,还能锻炼编程能力,提升系统设计和优化的思维。这对于他们在...

    java面试题归纳

    Java面试题归纳主要涵盖了许多核心的Java编程概念和技术,这些是面试官在招聘Java开发者时经常询问的主题。以下是一些重要的知识点,它们可能出现在面试题中: 1. **基础语法**:包括变量、数据类型、运算符、流程...

    Android底层结构-SDKService线程知多少[归纳].pdf

    3. 线程池(Threadpool):为了更有效地使用系统资源,Android使用线程池来执行后台任务。线程池可以重用线程,减少在创建和销毁线程上消耗的时间和资源。在【部分内容】中提到的“binding-timeThreadpool”可能是指...

    Java 多线程学习总结归纳(附代码)

    Java的Executor框架提供了线程池管理,可以有效控制并发数量,避免频繁创建和销毁线程的开销。ThreadPoolExecutor是核心类,可以通过参数定制线程池的行为。 以上内容涵盖了Java多线程的基础知识,包括创建、同步...

    java设计模式归纳,23种设计模式架构源码

    本资源包含了对23种经典设计模式的归纳,这些模式被广泛应用于构建可扩展、灵活且易于维护的Java应用程序。源码的提供使得学习者能够更直观地理解这些模式的实际应用。 1. **单例模式**:保证一个类只有一个实例,...

    C#知识点归纳,关于C#

    - `ThreadPool`:线程池,有效管理资源,减少创建销毁线程的开销。 - `async`/`await`:异步编程模型,简化异步操作,避免阻塞主线程。 9. **文件和IO操作** - `FileStream`、`StreamReader`、`StreamWriter`:...

    java面试题带答案[归纳].pdf

    3. **创建线程**:Java提供了多种创建线程的方式,包括继承Thread类、实现Runnable接口以及使用Executor框架创建线程池。推荐使用实现Runnable接口并结合Executor框架,因为它避免了单继承的限制,同时线程池能有效...

    Java基础知识点总结.docx

    4. 线程管理:线程调度、线程同步、线程通信、线程池等。 七、IO流(★★★★★): Java的IO流处理数据输入和输出,包括字节流、字符流、文件流、对象流等,还有缓冲流、转换流、管道流等。 八、网络编程: 涉及...

    Python多线程编程(6寸)[归纳].pdf

    而`threading`模块则更加强大,提供了更多的高级特性,如线程优先级、定时器和线程池。此外,`Queue`模块在多线程编程中常常用于线程间的数据交换,实现生产者-消费者模式。生产者线程将数据放入队列,而消费者线程...

    java实现多线程的网络并发服务器[归纳].pdf

    同时,线程池技术(如Java的`ExecutorService`)可以有效地管理和控制线程的数量,避免过度创建线程导致的资源浪费。 在实现过程中,为了保证线程安全,需要合理地使用同步机制,例如使用`synchronized`关键字来...

    手把手教你玩转网络编程模型之完成端口(CompletionPort)篇[归纳].pdf

    - **性能优化**:监控系统资源使用,根据负载动态调整线程池大小。 通过本篇文档,读者将能深入理解完成端口的工作原理,掌握如何在实际项目中使用完成端口编写高性能的网络服务程序。同时,提供的MFC图形界面示例...

    JAVA核心知识点整理

    此外,线程池管理和并发设计模式也是重要知识点。 五、Spring框架 Spring是Java企业级应用的事实标准,提供依赖注入(DI)、面向切面编程(AOP)、事务管理等功能。Spring Boot简化了配置,Spring Cloud则为微服务...

    509 道 Java 面试题汇总与解析 免费开源!!

    丰富的 Java 技术栈:基础和框架,线程池和锁优化,SpringBoot 和分布式消息队列,数据结构和常用算法,设计模式和 JVM 等 易学易会:提供了大量的图片说明和代码示例 你会获得什么 收获 Java 技术栈的核心知识点 这...

    视频教程.docx

    根据提供的文件信息,我们可以归纳出以下几个关键的知识点: ### 1. 饿汉式单例模式 #### 定义与特点 饿汉式单例模式是一种实现单例设计模式的方法,其特点是类在加载时就会创建一个实例。这种方式下,无论后续...

    nseit-2021-03:2021年3月为NSEIT归纳批次举办的Java-Oracle课程材料

    本课程材料"nseit-2021-03:2021年3月为NSEIT归纳批次举办的Java-Oracle课程材料"旨在为学员提供深入理解Java编程语言以及Oracle数据库管理系统的教育资源。这是一套全面的学习资料,适合对Java和Oracle感兴趣的初学...

    java精典编程100例 15

    虽然具体内容很少,但从标题、描述以及部分可见内容中,我们可以归纳并扩展出一些与Java多线程相关的知识点。 ### Java经典编程100例之多线程 #### 一、多线程基础 在Java编程中,多线程是实现并发处理的关键技术...

    java基础知识点框架图

    - **线程池**:ExecutorService和ThreadPoolExecutor,提高系统效率。 8. **反射机制**: - **Class类**:用于获取类的信息。 - **newInstance()**:动态创建对象。 - **getMethods()和getConstructors()**:...

Global site tag (gtag.js) - Google Analytics