`
kill2you
  • 浏览: 5057 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

线程池分析之一 ThreadPoolExecutor

阅读更多
简单来讲,创建线程池是为了提高当前应用的性能,减少因为系统创建线程所带来的性能消耗。
Jdk1.5中新增了java.util.concurrent.ThreadPoolExecutor线程池类,但是在创建时,强烈建议程序员使用较为方便的 Executors 工厂方法 Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)、Executors.newFixedThreadPool(int)(固定大小线程池)和 Executors.newSingleThreadExecutor()(单个后台线程)。
现在我们分析下ThreadPoolExecutor是如何实现线程池的。

ThreadPoolExecutor类本身是用来管理,创建,销毁线程池中的线程的,其中管理所需要用到的主要数据结构包括:
runState:表示当前管理线程池线程的运行状态
workQueue:任务池缓冲队列
workers:存储线程池中当前工作的线程集合
corePoolSize:线程池的最小值或者是核心值
maximumPoolSize:线程池的最大值
poolSize:当前线程的数量
handler:用来处理请求拒绝的类
threadFactory:线程工厂

内部私有类Worker,专门处理任务的线程,主要数据包括
firstTask:初始化构造器,传进来的任务
thread:对线程的引用

ThreadPoolExecutor类的线程启动和管理。
所有任务都是通过execute方法放入事先Runnable接口的任务。
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
		//addIfUnderCorePoolSize(command)方法主要是当poolSize < corePoolSize时,在线程池中创建线程
		//当创建成功时候返回true,否则false
            if (runState == RUNNING && workQueue.offer(command)) {
                if (runState != RUNNING || poolSize == 0)
                    ensureQueuedTaskHandled(command);
            }
            else if (!addIfUnderMaximumPoolSize(command))
                reject(command); // is shutdown or saturated
        }
    }

 addIfUnderCorePoolSize(command)
 if (poolSize < corePoolSize && runState == RUNNING)
//创建新的线程               
 t = addThread(firstTask);
//启动线程
 t.start();


   private Thread addThread(Runnable firstTask) {
    	//通过构造器,把第一个任务交给worker线程处理
    	Worker w = new Worker(firstTask);
    	//通过线程工厂包装worker线程,设置对应的属性
    	//newThread(w)方法如下
//    	Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(), 0);
//		if (t.isDaemon())
//		t.setDaemon(false);
//		if (t.getPriority() != Thread.NORM_PRIORITY)
//		t.setPriority(Thread.NORM_PRIORITY);
        Thread t = threadFactory.newThread(w);
        if (t != null) {
        	//实际上就是用Runnable生产了一个工人,而线程工厂使用了工人生产出一个线程,
        	//再用工人内部的一个属性指向这个线程。
        	//其实这里所做的是让t和w都有互相的引用,以便今后操作。
            w.thread = t;
            workers.add(w);
            int nt = ++poolSize;
            if (nt > largestPoolSize)
                largestPoolSize = nt;
        }
        return t;
    }


当线程管理池启动线程后调用worker的run方法
 
 public void run() {
            try {
                Runnable task = firstTask;
                firstTask = null;
                //当首任务不为空执行任务,或者能从workQueue中获取任务则执行
                //一直到没有任务执行位置
                while (task != null || (task = getTask()) != null) {
                	//真正执行任务的方法
                    runTask(task);
                    task = null;
                }
            } finally {
                workerDone(this);
            }
        }
//getTask()为线程管理池方法
 Runnable getTask() {
        for (;;) {
            try {
                int state = runState;
                //当runState大于SHUTDOWN时,无论任务队列是否有任务都不执行
                if (state > SHUTDOWN)
                    return null;
                Runnable r;
                //当线程池状态为SHUTDOWN的时候,继续把队列中的任务取出执行完
                if (state == SHUTDOWN)  // Help drain queue
                    r = workQueue.poll();
                //如果超过核心池,说明任务已经非常多了,工人线程等待一段时间还没有得到一个任务,
                //就马上返回不再等下去。
                else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
                    r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
                else
                	//正常情况,说明线程不多,用take,
                	//即使队列被锁住了,无论如何也要等到一个任务
                    r = workQueue.take();
                if (r != null)
                    return r;
                //如果取出的任务为null,判断工作线程是否可以退出
                //runState >= STOP ||workQueue.isEmpty() ||
                //(allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize));
                //以上任意一种情况成立,工作线程都退出
                if (workerCanExit()) {
                    if (runState >= SHUTDOWN) // Wake up others
                        interruptIdleWorkers();
                    return null;
                }
                // Else retry
            } catch (InterruptedException ie) {
                // On interruption, re-check runState
            }
        }
    }
		
		runTask(task);
                beforeExecute(thread, task);
                 //真正执行的任务
                    task.run();
                    afterExecute(task, null);

 void workerDone(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            //将工作线程移除出工作线程集合
            //使之变为非工作线程,
            //注:并没有将线程移除线程池,只是相当于标记线程是空闲还是繁忙
            workers.remove(w);
            if (--poolSize == 0)
                tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }


看看ThreadPoolExecutor线程池是的管理线程池的
1.当poolSize <=corePoolSize时,且线程池的状态为RUNNING时,产生新的worker线程处理任务。
2.当poolSize =corePoolSize时,将task放入工作队列。
3.当poolSize < maximumPoolSize时,并且工作队列满时,才会生成的新的线程。
4.当poolSize = maximumPoolSizee时,并且工作队列满时,使用拒绝策略拒绝请求。
5.当队列中没有任务的时候,且线程池中存在空闲的线程(根据构建线程池传入的keepAliveTime作为到
BlockingQueue获取任务的超时时间),这样线程池会收缩空闲线程到corePoolSize。

启动线程池看完了,我们再看看终止线程池是如何操作的。
首先看入口
shutdown(); 按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。
shutdownNow();尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。
 
//shutdown()调用的             
 for (Worker w : workers) {
                	//终止每个worker
                    w.interruptIfIdle();
                }

void interruptIfIdle() {
            final ReentrantLock runLock = this.runLock;
            if (runLock.tryLock()) {
                try {
		    if (thread != Thread.currentThread())
			thread.interrupt();
                } finally {
                    runLock.unlock();
                }
            }
        }


参考文章
http://www.blogjava.net/feuyeux/archive/2010/12/04/339799.html
http://blog.csdn.net/booboo2006/archive/2008/08/05/2770897.aspx
http://jclown.iteye.com/blog/769608
http://www.ibm.com/developerworks/cn/java/l-threadPool/
分享到:
评论

相关推荐

    12-线程池ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf

    通过上述对`ThreadPoolExecutor`线程池底层实现原理的解析,我们可以看到Java线程池的强大之处在于其高效的状态管理和任务调度机制。通过对`ctl`变量的巧妙利用,线程池能够有效地管理线程状态和数量,从而实现高...

    线程池分析与方案设计

    ### 线程池分析与方案设计 #### 线程池尺寸与性能分析 在计算机科学领域,线程池是一种广泛使用的优化技术,用于管理并行任务的执行。线程池通过预先创建一定数量的工作线程来处理提交的任务,避免了频繁创建和...

    JDK之ThreadPoolExecutor源码分析1

    《JDK之ThreadPoolExecutor源码分析1》 在Java编程中,线程池是一种高效的管理线程的方式,它通过复用已存在的线程来避免频繁创建和销毁线程带来的开销。ThreadPoolExecutor作为Java中的线程池实现,其内部机制相当...

    线程池的简单实现

    线程池是多线程编程中的一个重要概念,它在服务器端程序中被广泛使用,以提高资源利用率和...通过分析`ThreadPoolManager`、`WorkThread`、`Task`以及`TestThreadPool`这些类,我们可以更好地理解和实现线程池的机制。

    对象池&线程池&数据库连接池

    在软件开发中,资源管理是优化系统性能的关键因素之一。对象池、线程池和数据库连接池都是资源复用机制的实例,它们有效地解决了频繁创建和销毁对象带来的开销,提高了系统的效率。以下是对这些概念的详细解释: 1....

    Java代码构建一个线程池

    在现代软件开发中,多线程编程是提升程序性能、提高资源利用率的重要手段之一。特别是在服务器端应用中,合理地管理线程资源能够极大地提高系统的响应能力和处理效率。本文将详细介绍如何使用Java语言来构建一个简单...

    使用Java匿名内部类实现一个简单的线程池.txt

    在现代软件开发中,线程池是管理并发任务的重要工具之一。它能够有效地控制运行中的线程数量,合理分配系统资源,避免频繁创建销毁线程带来的性能开销。本篇文章将详细介绍如何利用Java中的匿名内部类来实现一个简单...

    java多线程相关面试题 1

    ThreadPoolExecutor 是 Java 中的一种线程池实现,它提供了一个灵活的线程池管理机制。ThreadPoolExecutor 的参数包括: * corePoolSize:线程池的核心线程数 * maximumPoolSize:线程池的最大线程数 * ...

    Java concurrency线程池之线程池原理(二)_动力节点Java学院整理

    线程池源码分析: 1. `newFixedThreadPool()`方法: 这个方法内部调用了`ThreadPoolExecutor`构造函数,传入参数分别代表核心线程数、最大线程数、空闲线程存活时间以及时间单位。核心线程数和最大线程数相等,...

    10393799ThreadPool2_java_DEMO_

    标题 "10393799ThreadPool2_java_DEMO_" 暗示这是一个关于Java线程池实现的示例代码。线程池是多线程编程中的一个重要概念,它提高...对于开发者来说,熟练掌握线程池的使用是提升代码性能和系统稳定性的重要技能之一。

    java八股文面试题包含答案及面试资料

    设计模式是衡量开发者设计能力的标准之一。常见的23种设计模式,如单例、工厂、观察者、装饰器、适配器、策略、模板方法等,面试中可能需要你根据实际情况来选择和解释适用的设计模式。 至于提供的“图灵学院VIP...

    java编程1-50例

    Java编程是计算机科学领域中最广泛使用的编程语言之一,尤其在企业级应用开发中占据着核心地位。本资源“java编程1-50例”显然是一份涵盖了基础到进阶的Java编程实例集,旨在帮助学习者通过实际操作来掌握Java语言的...

    ArchKnowledgeTree:架构师知识谱系梳理,包含Java core, JUC, JVM, MySQL,MQ, redis,分布式相关等各种知识点整理。是我按个人理解学习、整理出的一个知识库

    ArchKnowledgeTree ... 源码分析之Java线程池ThreadPoolExecutor 常见工具 [源码分析之Guava RateLimiter源码分析](source_code/源码分析之Guava RateLimiter源码分析.md) 源码分析之netty线程模型 Mes

    Android应用源码之下载网络图片 (整合多线程、内存缓存、本地文件缓存~).zip

    使用`AsyncTask`、`IntentService`或者线程池(如`ThreadPoolExecutor`)可以有效地管理这些后台任务。这份源码可能包含了如何在Android中创建并管理多个下载任务的示例。 内存缓存是一种提升性能的重要手段。在...

    Java面试题.zip

    Java作为世界上最受欢迎的编程语言之一,其面试题涵盖了广泛的领域,包括基础知识、数据结构与算法、多线程、网络编程、设计模式、JVM优化、框架应用等。下面,我们将根据"Java面试题.zip"中的内容,深入探讨这些...

    java性能调优

    在软件开发过程中,性能问题往往成为影响用户体验的关键因素之一。尤其对于使用Java语言构建的应用程序来说,由于其运行于JVM之上,性能调优显得尤为重要。本文将从编写高性能Java代码的角度出发,探讨常见的性能...

    恒生电子笔试题 Java

    你需要熟悉线程的创建(Thread类和Runnable接口)、同步机制(synchronized关键字,wait()、notify()方法)、线程池(ExecutorService,ThreadPoolExecutor)等。 5. **IO流**:Java的输入输出系统包括字符流和字节...

    并发编程之一 日常学习笔记

    接着,"Java并发线程池底层原理详解与源码分析",这部分内容通常会涵盖Java中的ExecutorService和ThreadPoolExecutor等类。线程池是管理线程的一种机制,它可以有效地控制运行的线程数量,避免过多创建和销毁线程...

    Java面试题(题库全).zip

    Java是世界上最流行的编程语言之一,尤其在企业级应用开发领域占据主导地位。这份"Java面试题(题库全).zip"压缩包包含了全面的Java面试题,旨在帮助求职者准备Java开发岗位的面试。文档"Java面试题(题库全).doc...

    程序员java基础面试题

    Java是世界上最流行的编程语言之一,尤其在企业级应用开发领域占据主导地位。对于程序员来说,掌握扎实的Java基础知识是至关重要的,这不仅有助于日常开发,也是面试时必不可少的知识储备。以下是一些Java基础面试题...

Global site tag (gtag.js) - Google Analytics