【Android】线程池原理及Java简单实现

线程池简介

  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。

  假设一个服务器完成一项任务所需时间为:

  1. T1 创建线程时间
  2. T2 在线程中执行任务的时间
  3. T3 销毁线程时间

  如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。

  一个线程池包括以下四个基本组成部分:

  1. 线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
  2. 工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
  3. 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
  4. 任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

  线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。

  它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。

  线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:

  假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目,而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。

代码实现中并没有实现任务接口,而是把Runnable对象加入到线程池管理器(ThreadPool),把剩下的事情交由线程池管理器(ThreadPool)来完成

用Java实现简单的线程池  

  线程池实现

  1 import java.util.List;
  2 import java.util.Vector;
  3
  4 /**
  5  *
  6  * @description:线程池
  7  * @author liuchengwei([email protected])
  8  * @date Sep 19, 2014 10:15:32 PM
  9  */
 10 public class ThreadPool {
 11     private static ThreadPool instance_ = null;
 12     //定义优先级别常数,空闲的线程按照优先级不同分别存放在三个vector中
 13     public static final int LOW_PRIORITY = 0;
 14     public static final int NORMAL_PRIORITY = 1;
 15     public static final int HIGH_PRIORITY = 2;
 16     //保存空闲线程的List,或者说它是"池"
 17     private List<PooledThread>[] idleThreads_;
 18     private boolean shutDown_ = false;
 19     private int threadCreationCounter_; //以创建的线程的个数
 20     private boolean debug_ = false; //是否输出调试信息
 21
 22     //构造函数,因为这个类视作为singleton实现的,因此构造函数为私有
 23     private ThreadPool() {
 24         // 产生空闲线程.三个vector分别存放分别处在三个优先级的线程的引用
 25         List[] idleThreads = { new Vector(5), new Vector(5), new Vector(5) };
 26         idleThreads_ = idleThreads;
 27         threadCreationCounter_ = 0;
 28     }
 29
 30     public int getCreatedThreadsCount() {
 31         return threadCreationCounter_;
 32     }
 33
 34     //通过这个函数得到线程池类的实例
 35     public static ThreadPool instance() {
 36         if (instance_ == null)
 37             instance_ = new ThreadPool();
 38         return instance_;
 39     }
 40
 41     public boolean isDebug() {
 42         return debug_;
 43     }
 44
 45     /**
 46      *
 47      * @description:
 48      * 将线程repoolingThread从新放回到池中,这个方式是同步方法。
 49      * 这个方法会在多线程的环境中调用,设计这个方法的目的是让工作者线程
 50      * 在执行完target中的任务后,调用池类的repool()方法,
 51      * 将线程自身从新放回到池中。只所以这么做是因为线程池并不能预见到
 52      * 工作者线程何时会完成任务。
 53      * @author liuchengwei([email protected])
 54      * @date Sep 19, 2014 10:15:59 PM
 55      */
 56     protected synchronized void repool(PooledThread repoolingThread) {
 57         if (!shutDown_) {
 58             if (debug_) {
 59                 System.out.println("ThreadPool.repool() : repooling ");
 60             }
 61             switch (repoolingThread.getPriority()) {
 62                 case Thread.MIN_PRIORITY: {
 63                     idleThreads_[LOW_PRIORITY].add(repoolingThread);
 64                     break;
 65                 }
 66                 case Thread.NORM_PRIORITY: {
 67                     idleThreads_[NORMAL_PRIORITY].add(repoolingThread);
 68                     break;
 69                 }
 70                 case Thread.MAX_PRIORITY: {
 71                     idleThreads_[HIGH_PRIORITY].add(repoolingThread);
 72                     break;
 73                 }
 74                 default:
 75                     throw new IllegalStateException("Illegal priority found while repooling a Thread!");
 76             }
 77             notifyAll();//通知所有的线程
 78         }
 79         else {
 80             if (debug_) {
 81                 System.out.println("ThreadPool.repool() : Destroying incoming thread.");
 82             }
 83             repoolingThread.shutDown();//关闭线程
 84         }
 85         if (debug_) {
 86             System.out.println("ThreadPool.recycle() : done.");
 87         }
 88     }
 89
 90     public void setDebug(boolean newDebug) {
 91         debug_ = newDebug;
 92     }
 93
 94     //停止池中所有线程
 95     public synchronized void shutdown() {
 96         shutDown_ = true;
 97         if (debug_) {
 98             System.out.println("ThreadPool : shutting down ");
 99         }
100         for (int prioIndex = 0; prioIndex <= HIGH_PRIORITY; prioIndex++) {
101             List prioThreads = idleThreads_[prioIndex];
102             for (int threadIndex = 0; threadIndex < prioThreads.size(); threadIndex++) {
103                 PooledThread idleThread = (PooledThread) prioThreads.get(threadIndex);
104                 idleThread.shutDown();
105             }
106         }
107         notifyAll();
108         if (debug_) {
109             System.out.println("ThreadPool : shutdown done.");
110         }
111     }
112
113     //以Runnable为target,从池中选择一个优先级为priority的线程创建线程并让线程运行。
114     public synchronized void start(Runnable target, int priority) {
115         PooledThread thread = null; //被选出来执行target的线程
116         List idleList = idleThreads_[priority];
117         if (idleList.size() > 0) {
118             /**
119              * 如果池中相应优先级的线程有空闲的,那么从中取出一个
120              * 设置它的target,并唤醒它
121              * 从空闲的线程队列中获取
122              *
123              * @author liuchengwei([email protected])
124              */
125             int lastIndex = idleList.size() - 1;
126             thread = (PooledThread) idleList.get(lastIndex);
127             idleList.remove(lastIndex);
128             thread.setTarget(target);
129         }
130         //池中没有相应优先级的线程
131         else {
132             threadCreationCounter_++;
133             // 创建新线程,
134             thread = new PooledThread(target, "PooledThread #" + threadCreationCounter_, this);
135             // 新线程放入池中
136             switch (priority) {
137                 case LOW_PRIORITY: {
138                     thread.setPriority(Thread.MIN_PRIORITY);
139                     break;
140                 }
141                 case NORMAL_PRIORITY: {
142                     thread.setPriority(Thread.NORM_PRIORITY);
143                     break;
144                 }
145                 case HIGH_PRIORITY: {
146                     thread.setPriority(Thread.MAX_PRIORITY);
147                     break;
148                 }
149                 default: {
150                     thread.setPriority(Thread.NORM_PRIORITY);
151                     break;
152                 }
153             }
154             //启动这个线程
155             thread.start();
156         }
157     }
158 }

  工作者线程实现

  1 /**
  2  *
  3  * @description:线程
  4  * @author liuchengwei([email protected])
  5  * @date Sep 19, 2014 9:39:34 PM
  6  */
  7 public class PooledThread extends Thread {
  8     private ThreadPool pool_; // 池中线程需要知道自己所在的池
  9     private Runnable target_; // 线程的任务
 10     private boolean shutDown_ = false;
 11     private boolean idle_ = false;//设置是否让线程处于等待状态
 12
 13     private PooledThread() {
 14         super();
 15     }
 16
 17     private PooledThread(Runnable target) {
 18         super(target); //初始化父类
 19     }
 20
 21     private PooledThread(Runnable target, String name) {
 22         super(target, name);
 23     }
 24
 25     public PooledThread(Runnable target, String name, ThreadPool pool) {
 26         super(name);
 27         pool_ = pool;
 28         target_ = target;
 29     }
 30
 31     private PooledThread(String name) {
 32         super(name);//初始化父类
 33     }
 34
 35     private PooledThread(ThreadGroup group, Runnable target) {
 36         super(group, target);
 37     }
 38
 39     private PooledThread(ThreadGroup group, Runnable target, String name) {
 40         super(group, target, name);
 41     }
 42
 43     private PooledThread(ThreadGroup group, String name) {
 44         super(group, name);
 45     }
 46
 47     public java.lang.Runnable getTarget() {
 48         return target_;
 49     }
 50
 51     public boolean isIdle() {
 52         return idle_;//返回当前的状态
 53     }
 54
 55     /**
 56      * 工作者线程与通常线程不同之处在于run()方法的不同。通常的线程,
 57      * 完成线程应该执行的代码后,自然退出,线程结束。
 58      * 虚拟机在线程结束后收回分配给线程的资源,线程对象被垃圾回收。
 59      * 而这在池化的工作者线程中是应该避免的,否则线程池就失去了意义。
 60      * 作为可以被放入池中并重新利用的工作者线程,它的run()方法不应该结束,
 61      * 随意,在随后可以看到的实现中,run()方法执行完target对象的代码后,
 62      * 就将自身repool(),然后调用wait()方法,使自己睡眠而不是退出循环和run()。
 63      * 这就使线程池实现的要点。
 64      *
 65      * @author liuchengwei([email protected])
 66      */
 67     public void run() {
 68         // 这个循环不能结束,除非池类要求线程结束
 69         // 每一次循环都会执行一次池类分配给的任务target
 70         while (!shutDown_) {
 71             idle_ = false;
 72             if (target_ != null) {
 73                 target_.run(); // 运行target中的代码
 74             }
 75             idle_ = true;
 76             try {
 77                 //线程通知池重新将自己放回到池中
 78                 pool_.repool(this); //
 79                 //进入池中后睡眠,等待被唤醒执行新的任务,
 80                 //这里是线程池中线程于普通线程的run()不同的地方。
 81                 synchronized (this) {
 82                     wait();
 83                 }
 84             }
 85             catch (InterruptedException ie) {
 86             }
 87             idle_ = false;
 88         }
 89         //循环这里不能结束,否则线程结束,资源被VM收回,
 90         //就无法起到线程池的作用了
 91     }
 92
 93     public synchronized void setTarget(java.lang.Runnable newTarget) {//设置新的target,并唤醒睡眠中的线程
 94         target_ = newTarget; // 新任务
 95         notifyAll(); // 唤醒睡眠的线程
 96     }
 97
 98     public synchronized void shutDown() {
 99         shutDown_ = true;
100         notifyAll();
101     }
102 }

  测试代码

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println("Testing ThreadPool ");
 4         System.out.println("Creating ThreadPool ");
 5         ThreadPool pool = ThreadPool.instance();
 6         pool.setDebug(true);
 7         class TestRunner implements Runnable {
 8             public int count = 0;
 9
10             public void run() {
11                 System.out.println("Testrunner sleeping 5 seconds ");
12                 //此方法使本线程睡眠5秒
13                 synchronized (this) {
14                     try {
15                         wait(5000);//等待5秒时间
16                     }
17                     catch (InterruptedException ioe) {
18                     }
19                 }
20                 System.out.println("Testrunner leaving  ");
21                 count++;
22             }
23         }
24         System.out.println("Starting a new thread ");
25         TestRunner runner = new TestRunner();
26         pool.start(runner, pool.HIGH_PRIORITY);
27         System.out.println("count : " + runner.count);
28         System.out.println("Thread count : " + pool.getCreatedThreadsCount());
29         pool.shutdown();
30     }
31
32 }

时间: 2024-10-12 10:32:18

【Android】线程池原理及Java简单实现的相关文章

线程池;java实现线程池原理

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙.如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值.超过最大值的线程可以排队,但他们要等到其他线程完成后才启动. 组成部分 1.线程池

AsyncTask,IntentService工作原理分析&amp;Android线程池

一,android中的主线程和子线程 android中的主线程可以认为是UI线程,在主线程不可以执行耗时的操作,否则就会给人一种卡顿的感觉.而主线程主要用于处理四大组件,以及处理它们和用户的交互.anroid的子线程的主要功能就是处理耗时操作. 要知道"在android3.0之后,要求网络访问必须在子线程执行,否则会抛出NetWorkOnMainThreadException异常." 二,Android中的线程形态 Android中的线程状态,除了传统的Thread,还包含AsyncT

java多线程系类:JUC线程池:03之线程池原理(二)(转)

概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代码(基于JDK1.7.0_40)线程池源码分析(一) 创建"线程池"(二) 添加任务到"线程池"(三) 关闭"线程池" 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509954.h

Android(java)学习笔记267:Android线程池

1. 线程池 (1)线程池的优点: 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销. 能有效控制线程池的最大并发数,避免大量的线程之间因相互抢占系统资源而导致的阻塞现象. 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能. (2)Android中的线程池: Android中的线程池的概念来源于Java中的Executor,Executor是一个借口,真正的线程池实现为ThreadPoolExecutor. ThreadPoolExecutor提供了一系列参数来配置

Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理 以下是本文的目录大纲: 一.shutdown()  --  温柔的终止线程池 interruptIdleWorkers()  --  中断空闲worker tryTerminate()  --  尝试终止线程池 二.shutdown

Java线程池原理

转自:https://www.jianshu.com/p/a166944f1e73 本篇文章主要介绍Java线程池的原理以及源码的分析 线程池的介绍 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池. 线程池的优点 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 第三:提高线程的可管理性.线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会

含源码解析,深入Java 线程池原理

从池化技术到底层实现,一篇文章带你贯通线程池技术. 1.池化技术简介 在系统开发过程中,我们经常会用到池化技术来减少系统消耗,提升系统性能. 在编程领域,比较典型的池化技术有: 线程池.连接池.内存池.对象池等. 对象池通过复用对象来减少创建对象.垃圾回收的开销:连接池(数据库连接池.Redis连接池和HTTP连接池等)通过复用TCP连接来减少创建和释放连接的时间.线程池通过复用线程提升性能.简单来说,池化技术就是通过复用来提升性能. 线程.内存.数据库的连接对象都是资源,在程序中,当你创建一个

Java 线程池原理分析

1.简介 线程池可以简单看做是一组线程的集合,通过使用线程池,我们可以方便的复用线程,避免了频繁创建和销毁线程所带来的开销.在应用上,线程池可应用在后端相关服务中.比如 Web 服务器,数据库服务器等.以 Web 服务器为例,假如 Web 服务器会收到大量短时的 HTTP 请求,如果此时我们简单的为每个 HTTP 请求创建一个处理线程,那么服务器的资源将会很快被耗尽.当然我们也可以自己去管理并复用已创建的线程,以限制资源的消耗量,但这样会使用程序的逻辑变复杂.好在,幸运的是,我们不必那样做.在

Java(Android)线程池 总结

一种是使用Executors工厂生产线程池:另一种是直接使用ThreadPoolExecutor自定义. Executors工厂生产线程池 Java(Android)线程池 Trinea 介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new Thread吗? Java 1 2 3 4 5 6 7 newThread(newRunnable(){ @Ove