- 浏览: 454241 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
- 用途及用法
网络请求通常有两种形式:第一种,请求不是很频繁,而且每次连接后会保持相当一段时间来读数据或者写数据,最后断开,如文件下载,网络流媒体等。另一种形式是请求频繁,但是连接上以后读/写很少量的数据就断开连接。考虑到服务的并发问题,如果每个请求来到以后服务都为它启动一个线程,那么这对服务的资源可能会造成很大的浪费,特别是第二种情况。因为通常情况下,创建线程是需要一定的耗时的,设这个时间为T1,而连接后读/写服务的时间为T2,当T1>>T2时,我们就应当考虑一种策略或者机制来控制,使得服务对于第二种请求方式也能在较低的功耗下完成。
通常,我们可以用线程池来解决这个问题,首先,在服务启动的时候,我们可以启动好几个线程,并用一个容器(如线程池)来管理这些线程。当请求到来时,可以从池中去一个线程出来,执行任务(通常是对请求的响应),当任务结束后,再将这个线程放入池中备用;如果请求到来而池中没有空闲的线程,该请求需要排队等候。最后,当服务关闭时销毁该池即可。
- 结构
线程池中通常由这样几个概念(接口)组成:
- 线程池(Thread pool ),池是一个容器,容器中有很多个执行器,每一个执行器是一个线程。当然,这个容器的实现,可以是链表,可以是数组等等,不需要关心,需要关心的是,池必须提供一个可以从中取出执行器 的方法,可能还需要一个池中现有活动线程数方法,销毁池的方法等。
- 执行器(Executor ),每个执行器是一个线程,每个执行器可以执行一个任务 ,任务是做什么,此时还不很明确,它需要提供任务的setter/getter方法,并且作为一个线程,他可以独立运行,执行器执行完自身后,需要将自身放入池中。
- 任务(Task ),任务是每个线程具体要做的事,如资源下载,播放flash片段,打印一段文字到控制台等等,它本身不能执行,而需要将自身交给执行器。
整个池的机制和结构就是这样,当然,需要一个调度者(scheduler)来协调主线程和池的关系。结构,或者接口的目的是为了让我们从细节中解脱出来,从一个比较抽象的层次来描述系统,这样的好处是简单,而且设计出来的框架比较通用,可以适应很多相近相似的情况。由于Task具体干什么我们不知道,所以它几乎可以干任何适应于上边总结的网络连接的第二种情况(T1>>T2)。
- 类的结构图
虽然为一个简单的实现设计一个标准的UML视图是不太现实的,但是这是一种受鼓励的做法,至少应该用铅笔在草纸上画出相关的视图,这样可以帮助以后的维护和更高级的扩展。
- 线程池的简单实现
实现可以是通过多种语言的,我们在此选择面向对象的JAVA,而如果你使用C的话,也没有问题,问题在上一小节已经描述清楚,语言是不重要的。
池是一个容器,我们考虑使用java.util.LinkedList类(可能由于它的长度是可变的,而且不需要我们使用者来考虑),也就是说,池需要维护一个链表。
public interface Pool {//池接口 Executor getExecutor(); void destroy(); }
public interface Executor {//执行器接口 void setTask(Task task); Task getTask(); void startTask(); }
鉴于执行器是池中的对象,而且外部没有必要知道其细节,我们考虑将Executor接口的实现做为Pool接口的实现的内部类。这样做的另一个好处是,更便于池的管理。
import java.util.LinkedList; import java.util.Properties; import redesigned.utils.PropReader; public class ThreadPool implements Pool{ private boolean isShut; private LinkedList pool; private static Properties prop = PropReader.getProperties("webconfig.properties"); private int size = Integer.parseInt(prop.getProperty("threadsperpage", "3")); public ThreadPool(){ // read configuration and set the // content of pool by objects of Executor isShut = false;//set the status of pool to active pool = new LinkedList(); for(int i = 0; i < size; i++){ Executor executor = new ExecutorImpl();//new a executor thread pool.add(executor);//add it to pool ((ExecutorImpl)executor).start();//start it } } public void destroy() {//Destroy synchronized(pool){ isShut = true;//set the status of pool to inactive pool.notifyAll();//notify all listener. pool.clear();//clear the list of threads } } public Executor getExecutor(){ Executor ret = null; synchronized(pool){//return if any. if(pool.size() > 0){ ret = (Executor)pool.removeFirst(); }else{ try { pool.wait(); } catch (InterruptedException e) { e.printStackTrace(); } ret = (Executor)pool.removeFirst(); } } return ret; } Executor接口的实现作为ThreadPool的内部类 private class ExecutorImpl extends Thread implements Executor{ private Task task; private Object lock = new Object(); //private boolean loop = true; public ExecutorImpl(){} public Task getTask() { return this.task; } public void setTask(Task task) { this.task = task; } public void startTask(){ //System.out.println("start here"); synchronized(lock){ lock.notify(); } } public void run(){ //get a task if any //then run it //then put self to pool while(!isShut){ synchronized(lock){ try { lock.wait();//wait for resource } catch (InterruptedException e) { e.printStackTrace(); } } getTask().execute();//execute the task synchronized(pool){//put it self to the pool when finish the task pool.addFirst(ExecutorImpl.this); pool.notifyAll(); } } } } }
好了,池设计好了,再来看看任务(Task)的接口和实现
public interface Task {//这个接口也比较简单,可以执行,可以取到执行结果 void execute(); byte[] getResult(); }
Task的实现可以是多种多样的,下边的例子是一个加载资源的Task.使用方式
Pool pool = new ThreadPool();// new a ThreadPool //load resources on each page, and start #s of thread. for(int i = 0; i < resourceList.size();i++){ Executor executor = pool.getExecutor(); // get Executor form pool Task resourceLoader = new ResourceLoader((String)resourceList.get(i)); executor.setTask(resourceLoader); // set the task to executor executor.startTask(); // try to start the executor. } //wait while all task are done, the destroy the pool. pool.destroy();
- 优势,或者适用范围
- 在并发时,需要被并发的线程不需要知道自己什么时候需要被启动,它子需要考虑这样一种情况:它自己从一个地方取出来一个执行器,然后把任务交给执行器,然后等待执行器结束即可,他关心的是自己所需要干的事,或者自己负责的事。这样,大家都简单,因为只需要做好自己的事情就好了。面向对象的一个秘诀为:永远相信合作者,使用别人的接口而不是自己去实现所有的接口。
- 这种T1>>T2的请求方式在网络中固然是常见的,在实际问题中同样是常见的。因此,掌握这种模式可能会对我们以后的程序设计提供方便和好处。
- 小结
同步问题: 同步在线程的并发中意义非常之大,对临界资源的控制是并发时最关键的地方。如在线程池中,当池中没有空闲的线程时,新来的请求就必须等待,而一旦一个Task运行结束后,一方面将自己放入池中,一方面需要通知等待在pool中的其他线程。每一个执行器线程,一开始启动,则进入等待状态,此时不会消耗CPU资源。而当在外部调用执行器的startTask()方法,即可通知线程从等待状态中醒来,去出Task,执行之,将执行器本身放入池中,然后继续等待。
当然,实现的策略是可以多种多样的,但是问题的本质已经在第二小节结构 很明确的被定义了。
最近开始学习JAVA,同时也开始熟悉面向对象的思维方式,这篇日志,一来作为一个备忘,二来可以对可能需要的人提供帮助。以上可以算作是小结。
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2380第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6491基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4309前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 2012前言 借助JavaScript脚本 ... -
函数式编程(javascirpt)
2009-04-18 22:18 1289前言 Javascript,有人称 ... -
C和指针
2009-05-21 23:15 1134前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
C和指针(续)
2009-05-25 23:41 1384前言 上一篇《C和指针》可能对关于C和指针的有些内容没有说透 ... -
有限自动机与建模
2009-06-06 10:48 1827前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1454前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1370前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3812第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3681接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2930第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3926第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 4079第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4594第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2149前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 5112第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6181第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第2章 基本概念
2010-04-03 19:44 5740第二章 基本概念 ...
相关推荐
下面的例子中,我们有一个并行流,这个并行流使用了一个自定义的线程池去计算1到 1,000,000的和。 知识点:可以使用ForkJoinPool的构造方法并设定并行级别来创建一个自定义的线程池。 4. 总结 我们简要地看了一下...
NULL 博文链接:https://yulincqupt.iteye.com/blog/1673919
线程池示例(包含自定义拒绝策略),演示了如何创建一个线程池,以及添加到队列的过程,先添加到工作线程,然后是缓存队列,最后是创建临时线程
目标:Java中多线程技术是一个难点,但是也是一个核心技术。因为Java本身就是一个多线程语言。本人目前在给46班讲授Swing的网络编程--使用Swing来模拟真实的QQ实时聊天软件。因为涉及到Socket编程,所以一定会使用多...
通常,开发者会自定义一个线程池类,管理一组Boost线程,维护一个任务队列,并提供添加任务和启动/停止线程池的方法。 `ThreadPoolDemo.rar`和`thread_pool.rar`可能是线程池的实现示例,可能包含了一些基本的...
当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。 为什么要用线程池: 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务 可以根据系统的...
当一个新任务提交时,线程池会分配一个空闲线程来执行任务,而不是每次都创建新的线程。这降低了创建和销毁线程的开销,提高了系统性能。在Java中,`java.util.concurrent`包下的`ExecutorService`和`...
Java线程池的核心接口是`ExecutorService`,它是`Executor`接口的一个实现,提供了更丰富的线程管理功能。`ExecutorService`可以管理和调度任务,支持定时执行、定期执行以及并发数控制等高级特性。在Java中,线程池...
例如,在代码示例中,使用Executors.newSingleThreadExecutor()创建了一个单线程线程池,并且通过pool.execute(t1);等方法提交了多个任务到线程池中执行。最后,通过调用pool.shutdown()方法来关闭线程池,释放相关...
【自定义Java线程池实现】 在Java编程中,线程池是一种高效管理线程资源的方式,可以提高系统的性能和响应速度。本篇将探讨如何模拟Java的JDK线程池执行流程,以理解其设计原理。核心知识点包括线程池的执行策略、...
Java线程池是一种高效管理并发任务的机制,它在多线程编程中扮演着至关重要的角色。线程池通过预先创建并维护一组可重用线程来提高性能和响应速度,避免频繁创建和销毁线程所带来的开销。在这个"Java-Thread-Pool-...
总之,`uThreadPool线程池示例`是一个很好的学习资源,它演示了如何利用线程池处理大型计算任务,同时展示了多线程编程中的并发控制和任务调度。对于想要提升并发编程能力的开发者来说,这是一个值得研究的案例。
1. SingleThreadExecutor:这个线程池仅使用一个线程来执行所有任务,确保任务按提交顺序执行,不会发生并发,适合于任务之间需要保持执行顺序的场景。 2. FixedThreadPool:固定容量的线程池,核心线程数等于最大...
【Java线程池实现】 Java通过`java.util.concurrent`包提供了线程池的实现,如`ExecutorService`接口和`ThreadPoolExecutor`类。`ThreadPoolExecutor`允许开发者自定义线程池的核心参数,如核心线程数、最大线程数...
Java内置的`java.util.concurrent`包提供了一个强大的线程池实现——`ExecutorService`,通过`ThreadPoolExecutor`类可以自定义线程池配置。线程池通常包含核心线程数、最大线程数、线程空闲时间、工作队列等参数,...
线程池是多线程编程中的一个重要概念,它是一种线程使用模式,通过维护一组可重用线程来提高程序的性能和响应速度。在Java中,我们可以使用`java.util.concurrent`包下的`ExecutorService`接口及其实现类,如`...
Java代码中展示的`ThreadPool`类是作者实现的一个简单线程池示例,使用了`LinkedList`作为工作队列,`ThreadPool`类继承了`ThreadGroup`,这在JDK 1.4版本中是一种常见实现方式。但在JDK 1.5及以上版本,推荐使用`...
主要介绍了Java中的线程池,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
以下是一个简单的线程池创建示例: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; ExecutorService executor =...