- 浏览: 176462 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (159)
- java常用 (28)
- Spring Security (0)
- tomcat (2)
- orcale (4)
- rmi (6)
- jvm (5)
- html (0)
- hibernate (0)
- javascript (5)
- log4j (5)
- struts (5)
- jdbc (0)
- jquery (0)
- json (0)
- jstl (0)
- jboss (0)
- JCaptcha (0)
- jpa (0)
- oscache (0)
- 项目管理 (8)
- ExtJs (10)
- 设计模式 (3)
- jsp (3)
- 错误归档 (1)
- maven (5)
- java多线程 (10)
- quartz (4)
- spring (9)
- memcache (3)
- java笔试面试 (3)
- xml (3)
- hadoop (5)
- velocity (2)
- jetty (3)
- http (1)
- linux (2)
- hbase (2)
- mysql (12)
- mybatis (8)
- web安全 (1)
- hive (2)
- 其他 (1)
最新评论
· 用途及用法
网络请求通常有两种形式:第一种,请求不是很频繁,而且每次连接后会保持相当一段时间来读数据或者写数据,最后断开,如文件下载,网络流媒体等。另一种形式是请求频繁,但是连接上以后读/写很少量的数据就断开连接。考虑到服务的并发问题,如果每个请求来到以后服务都为它启动一个线程,那么这对服务的资源可能会造成很大的浪费,特别是第二种情况。因为通常情况下,创建线程是需要一定的耗时的,设这个时间为T1,而连接后读/写服务的时间为T2,当T1>>T2时,我们就应当考虑一种策略或者机制来控制,使得服务对于第二种请求方式也能在较低的功耗下完成。
通常,我们可以用线程池来解决这个问题,首先,在服务启动的时候,我们可以启动好几个线程,并用一个容器(如线程池)来管理这些线程。当请求到来时,可以从池中去一个线程出来,执行任务(通常是对请求的响应),当任务结束后,再将这个线程放入池中备用;如果请求到来而池中没有空闲的线程,该请求需要排队等候。最后,当服务关闭时销毁该池即可。
· 结构
线程池中通常由这样几个概念(接口)组成:
1 线程池(Thread pool ),池是一个容器,容器中有很多个执行器,每一个执行器是一个线程。当然,这个容器的实现,可以是链表,可以是数组等等,不需要关心,需要关心的是,池必须提供一个可以从中取出执行器 的方法,可能还需要一个池中现有活动线程数方法,销毁池的方法等。
2 执行器(Executor ),每个执行器是一个线程,每个执行器可以执行一个任务 ,任务是做什么,此时还不很明确,它需要提供任务的setter/getter方法,并且作为一个线程,他可以独立运行,执行器执行完自身后,需要将自身放入池中。
3 任务(Task ),任务是每个线程具体要做的事,如资源下载,播放flash片段,打印一段文字到控制台等等,它本身不能执行,而需要将自身交给执行器。
整个池的机制和结构就是这样,当然,需要一个调度者(scheduler)来协调主线程和池的关系。结构,或者接口的目的是为了让我们从细节中解脱出来,从一个比较抽象的层次来描述系统,这样的好处是简单,而且设计出来的框架比较通用,可以适应很多相近相似的情况。由于Task具体干什么我们不知道,所以它几乎可以干任何适应于上边总结的网络连接的第二种情况(T1>>T2)。
· 类的结构图
虽然为一个简单的实现设计一个标准的UML视图是不太现实的,但是这是一种受鼓励的做法,至少应该用铅笔在草纸上画出相关的视图,这样可以帮助以后的维护和更高级的扩展。
· 线程池的简单实现
实现可以是通过多种语言的,我们在此选择面向对象的JAVA,而如果你使用C的话,也没有问题,问题在上一小节已经描述清楚,语言是不重要的。
池是一个容器,我们考虑使用java.util.LinkedList类(可能由于它的长度是可变的,而且不需要我们使用者来考虑),也就是说,池需要维护一个链表。
4 public interface Pool { //池接口
5 Executor getExecutor();
6 void destroy();
7 }
[java]view plaincopyprint?
8 public interface Pool {//池接口
9 Executor getExecutor();
10 void destroy();
11 }
12 public interface Executor { //执行器接口
13 void setTask(Task task);
14 Task getTask();
15 void startTask();
16 }
[java]view plaincopyprint?
17 public interface Executor {//执行器接口
18 void setTask(Task task);
19 Task getTask();
20 void startTask();
21 }
鉴于执行器是池中的对象,而且外部没有必要知道其细节,我们考虑将Executor接口的实现做为Pool接口的实现的内部类。这样做的另一个好处是,更便于池的管理。
22 import java.util.LinkedList;
23 import java.util.Properties;
24
25 import redesigned.utils.PropReader;
26
27 public class ThreadPool implements Pool{
28 private boolean isShut;
29 private LinkedList pool;
30 private static Properties prop = PropReader.getProperties("webconfig.properties");
31 private int size = Integer.parseInt(prop.getProperty("threadsperpage", "3"));
32 public ThreadPool(){
33 // read configuration and set the
34 // content of pool by objects of Executor
35 isShut = false;//set the status of pool to active
36 pool = new LinkedList();
37 for(int i = 0; i < size; i++){
38 Executor executor = new ExecutorImpl();//new a executor thread
39 pool.add(executor);//add it to pool
40 ((ExecutorImpl)executor).start();//start it
41 }
42 }
43 public void destroy() {//Destroy
44 synchronized(pool){
45 isShut = true;//set the status of pool to inactive
46 pool.notifyAll();//notify all listener.
47 pool.clear();//clear the list of threads
48 }
49 }
50
51 public Executor getExecutor(){
52 Executor ret = null;
53 synchronized(pool){//return if any.
54 if(pool.size() > 0){
55 ret = (Executor)pool.removeFirst();
56 }else{
57 try {
58 pool.wait();
59 } catch (InterruptedException e) {
60 e.printStackTrace();
61 }
62 ret = (Executor)pool.removeFirst();
63 }
64 }
65 return ret;
66 }
67
68 Executor接口的实现作为ThreadPool的内部类
69 private class ExecutorImpl extends Thread implements Executor{
70 private Task task;
71 private Object lock = new Object();
72 //private boolean loop = true;
73 public ExecutorImpl(){}
74 public Task getTask() {
75 return this.task;
76 }
77
78 public void setTask(Task task) {
79 this.task = task;
80 }
81 public void startTask(){
82 //System.out.println("start here");
83 synchronized(lock){
84 lock.notify();
85 }
86 }
87 public void run(){
88 //get a task if any
89 //then run it
90 //then put self to pool
91 while(!isShut){
92 synchronized(lock){
93 try {
94 lock.wait();//wait for resource
95 } catch (InterruptedException e) {
96 e.printStackTrace();
97 }
98 }
99 getTask().execute();//execute the task
100 synchronized(pool){//put it self to the pool when finish the task
101 pool.addFirst(ExecutorImpl.this);
102 pool.notifyAll();
103 }
104 }
105 }
106 }
107 }
[java]view plaincopyprint?
108 import java.util.LinkedList;
109 import java.util.Properties;
110
111 import redesigned.utils.PropReader;
112
113 public class ThreadPool implements Pool{
114 private boolean isShut;
115 private LinkedList pool;
116 private static Properties prop = PropReader.getProperties("webconfig.properties");
117 private int size = Integer.parseInt(prop.getProperty("threadsperpage", "3"));
118 public ThreadPool(){
119 // read configuration and set the
120 // content of pool by objects of Executor
121 isShut = false;//set the status of pool to active
122 pool = new LinkedList();
123 for(int i = 0; i < size; i++){
124 Executor executor = new ExecutorImpl();//new a executor thread
125 pool.add(executor);//add it to pool
126 ((ExecutorImpl)executor).start();//start it
127 }
128 }
129 public void destroy() {//Destroy
130 synchronized(pool){
131 isShut = true;//set the status of pool to inactive
132 pool.notifyAll();//notify all listener.
133 pool.clear();//clear the list of threads
134 }
135 }
136
137 public Executor getExecutor(){
138 Executor ret = null;
139 synchronized(pool){//return if any.
140 if(pool.size() > 0){
141 ret = (Executor)pool.removeFirst();
142 }else{
143 try {
144 pool.wait();
145 } catch (InterruptedException e) {
146 e.printStackTrace();
147 }
148 ret = (Executor)pool.removeFirst();
149 }
150 }
151 return ret;
152 }
153
154 Executor接口的实现作为ThreadPool的内部类
155 private class ExecutorImpl extends Thread implements Executor{
156 private Task task;
157 private Object lock = new Object();
158 //private boolean loop = true;
159 public ExecutorImpl(){}
160 public Task getTask() {
161 return this.task;
162 }
163
164 public void setTask(Task task) {
165 this.task = task;
166 }
167 public void startTask(){
168 //System.out.println("start here");
169 synchronized(lock){
170 lock.notify();
171 }
172 }
173 public void run(){
174 //get a task if any
175 //then run it
176 //then put self to pool
177 while(!isShut){
178 synchronized(lock){
179 try {
180 lock.wait();//wait for resource
181 } catch (InterruptedException e) {
182 e.printStackTrace();
183 }
184 }
185 getTask().execute();//execute the task
186 synchronized(pool){//put it self to the pool when finish the task
187 pool.addFirst(ExecutorImpl.this);
188 pool.notifyAll();
189 }
190 }
191 }
192 }
193 }
好了,池设计好了,再来看看任务(Task)的接口和实现
194 public interface Task { //这个接口也比较简单,可以执行,可以取到执行结果
195 void execute();
196 byte[] getResult();
197 }
[java]view plaincopyprint?
198 public interface Task {//这个接口也比较简单,可以执行,可以取到执行结果
199 void execute();
200 byte[] getResult();
201 }
Task的实现可以是多种多样的,下边的例子是一个加载资源的Task.使用方式
202 Pool pool = new ThreadPool(); // new a ThreadPool
203 //load resources on each page, and start #s of thread.
204 for(int i = 0; i < resourceList.size();i++){
205 Executor executor = pool.getExecutor(); // get Executor form pool
206 Task resourceLoader = new ResourceLoader((String)resourceList.get(i));
207 executor.setTask(resourceLoader); // set the task to executor
208 executor.startTask(); // try to start the executor.
209 }
210
211 //wait while all task are done, the destroy the pool.
212 pool.destroy();
[java]view plaincopyprint?
213 Pool pool = new ThreadPool();// new a ThreadPool
214 //load resources on each page, and start #s of thread.
215 for(int i = 0; i < resourceList.size();i++){
216 Executor executor = pool.getExecutor(); // get Executor form pool
217 Task resourceLoader = new ResourceLoader((String)resourceList.get(i));
218 executor.setTask(resourceLoader); // set the task to executor
219 executor.startTask(); // try to start the executor.
220 }
221
222 //wait while all task are done, the destroy the pool.
223 pool.destroy();
· 优势,或者适用范围
224 在并发时,需要被并发的线程不需要知道自己什么时候需要被启动,它子需要考虑这样一种情况:它自己从一个地方取出来一个执行器,然后把任务交给执行器,然后等待执行器结束即可,他关心的是自己所需要干的事,或者自己负责的事。这样,大家都简单,因为只需要做好自己的事情就好了。面向对象的一个秘诀为:永远相信合作者,使用别人的接口而不是自己去实现所有的接口。
225 这种T1>>T2的请求方式在网络中固然是常见的,在实际问题中同样是常见的。因此,掌握这种模式可能会对我们以后的程序设计提供方便和好处。
· 小结
同步问题: 同步在线程的并发中意义非常之大,对临界资源的控制是并发时最关键的地方。如在线程池中,当池中没有空闲的线程时,新来的请求就必须等待,而一旦一个Task运行结束后,一方面将自己放入池中,一方面需要通知等待在pool中的其他线程。每一个执行器线程,一开始启动,则进入等待状态,此时不会消耗CPU资源。而当在外部调用执行器的startTask()方法,即可通知线程从等待状态中醒来,去出Task,执行之,将执行器本身放入池中,然后继续等待。
当然,实现的策略是可以多种多样的,但是问题的本质已经在第二小节结构 很明确的被定义了。
最近开始学习JAVA,同时也开始熟悉面向对象的思维方式,这篇日志,一来作为一个备忘,二来可以对可能需要的人提供帮助。以上可以算作是小结。
发表评论
-
说一说java的concurrent包-系列文章
2013-03-05 09:47 859说一说java的concurrent包- ... -
java并发编程:定制线程池的大小
2013-03-05 09:44 1366java并发编程:定制线程池的大小 ... -
java.util.concurrent包应用1
2013-03-05 09:33 705java.util.concurrent包应用1 ... -
ThreadPoolExecutor jdk1.5中的线程池使用简介
2013-03-05 09:21 655一、简介 线程池类为 java.util.conc ... -
CAS原理 java 并发
2013-03-05 09:18 726CAS原理 在JDK 5之前Jav ... -
Java多线程Synchronized的注意细节
2013-03-04 20:03 645Java多线程Synchronized的 ... -
tomcat中多线程web服务的关闭
2012-08-23 22:52 1382摘要: 问题:将多线程web服务部署于tomcat中 ... -
JDK自带线程池总类介绍介绍
2012-08-23 22:44 830JDK自带线程池总类介绍介绍: 1、newFi ... -
java线程池
2012-08-22 20:40 882线程池的作用: 线程池作用就是限制系统中执行线程的 ...
相关推荐
Java 线程池例子 ThreadPoolExecutor Java 中的线程池是指一个容器,里面包含了多个线程,这些线程可以重复使用,以避免频繁创建和销毁线程的开销。ThreadPoolExecutor 是 Java 中一个非常重要的线程池实现类,它...
线程池里的线程等待等待队列里的线程执行,等待队列里的等待线程池里的完成,相互等待
Java线程池是一种高效管理线程的技术,它可以帮助开发者更好地控制并发执行的线程数量,避免资源浪费,提高系统性能。在Java中,线程池是通过`java.util.concurrent`包中的`ExecutorService`接口及其实现类来实现的...
Java线程池是Java并发编程中的重要组成部分,它允许开发者管理多个线程并有效地调度任务。线程池通过ThreadPoolExecutor类实现,这是一个高度可配置的工具,能够根据具体需求定制线程的创建、管理和销毁策略。 ...
Java线程池与反射机制是Java编程中两个重要的概念,它们在实际开发中扮演着至关重要的角色。线程池能够有效地管理和控制并发执行的任务,而反射机制则允许我们在运行时动态地访问和修改类的信息。 首先,让我们深入...
### Java线程池详解 #### 引言 在现代计算机科学中,线程作为轻量级的进程,已经成为操作系统和应用程序提高并发性、优化资源利用的关键技术之一。线程池,作为线程管理的一种高级机制,更是现代软件工程中不可或...
【标题】"火山安卓编程线程池例子"主要聚焦于Android平台上的多线程编程,尤其是使用火山编程框架实现线程池的示例。在Android应用开发中,线程池是一种有效的管理并发任务的方式,它可以帮助优化系统资源的使用,...
Java线程池是一种高效管理线程资源的工具,它的出现是为了优化系统性能,尤其是在需要频繁创建和销毁线程的情况下。由于操作系统创建新线程需要进行内存分配、上下文切换等操作,这涉及到一定的开销。因此,使用...
请最好使用MyEclipse导入工程,或者直接把src中的java文件拷贝到其他工程也可以使用,对想理解线程池概念的同学有很好的帮助
线程池示例(包含自定义拒绝策略),演示了如何创建一个线程池,以及添加到队列的过程,先添加到工作线程,然后是缓存队列,最后是创建临时线程
Java的`java.util.concurrent`包提供了`ExecutorService`接口和相关的实现类,如`ThreadPoolExecutor`,用于构建和管理线程池。通过设置核心线程数、最大线程数、线程存活时间等参数,可以定制适合不同场景的线程池...
java 线程池 实现 例子,线程池实例
corePoolSize:核心池的大小,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; ...
java代码 ThreadPoolExecutor线程池并发测试例子如有误欢迎指正
线程池的例子代码通常包括以下几个部分: - 创建线程池:设置线程池的参数,如最小线程数、最大线程数、线程空闲时间等。 - 提交任务:将需要执行的任务(通常是Runnable或Callable对象)提交给线程池。 - 执行任务...
Java线程池工作队列饱和策略代码示例 Java线程池工作队列饱和策略是Java并发编程中的一种重要机制,用于处理线程池中工作队列的饱和问题。在本文中,我们将详细介绍Java线程池工作队列饱和策略的概念、原理和实现。...
Java8并行流中自定义线程池操作示例 Java8并行流中自定义线程池操作示例主要介绍了Java8并行流中自定义线程池操作,结合实例形式分析了并行流的相关概念、定义及自定义线程池的相关操作技巧。 1. 概览 Java8引入了...
Java线程池是Java语言中一个非常重要的特性,特别是在多线程编程中,它通过管理和控制线程的创建和执行,有效地提高了程序的性能和资源利用率。线程池的引入始于JDK 1.5,它引入了`java.util.concurrent`包,提供了`...
在Android开发中,Java线程池是一个至关重要的概念,它能有效地管理多个并发任务,提高应用性能并降低资源消耗。线程池通过复用已创建的线程来避免频繁创建和销毁线程带来的开销,从而提升系统效率。在本教程中,...