使用线程池优化Echo模型
在上一篇文章中 http://www.cnblogs.com/gosaint/p/8492356.html 我阐述了使用线程为每一个客户端创建一个工作线程来负责任务的执行。但是会存在如下的问题
- 服务器创建线程开销很大,有可能服务器创建线程消耗资源要比单独的和客户端通信所消耗的资源要大
- 如果存在大量的线程要同时创建,那么存在的内存开销很大。可能导致服务器系统内存不够
- 线程之间的切换消耗了大量的资源
创建线程池可以较少线程的创建和销毁的开销,并且根据实际情况动态的调整线程池的大小。
(1) 自定以线程池,让它继承ThreadGroup类

如下代码是自定义线程池代码的实现
package com.asiaInfo.caozg.ch_03.threadPool; import java.util.LinkedList; /**
* @Authgor: gosaint
* @Description:
* @Date Created in 15:39 2018/3/2
* @Modified By:自定义线程池的实现
*/
public class ThreadPool extends ThreadGroup { private boolean isClosed = false;//线程池是否关闭
private LinkedList<Runnable> workQuee;//表示工作队列
private static int threadPoolID;//表示线程池ID
private int workThreadID;//表示工作线程池ID public ThreadPool(int poolSize) {
//poolSize表示线程池中工作线程的数目
//每一次的初始化,线程池ID都会自动增加
super("ThreadPool-" + (threadPoolID++));
//设置为守护线程
setDaemon(true);
workQuee = new LinkedList<>();//创建工作队列
for (int i = 0; i < poolSize; i++) {
new WorkThread().start();
}
} /**
* 向工作队列中添加一个新的任务,让工作线程去执行
*
* @param task
*/
public synchronized void execute(Runnable task) {
if (isClosed) {
//线程池关闭,则抛出如下的异常
throw new IllegalStateException();
}
if (task != null) {
workQuee.add(task);
notify();//唤醒正在等待获取任务的工作线程getTask();
}
} /**
* 从工作队列中取出一个线程,让线程执行任务
*
* @return
* @throws InterruptedException
*/
public synchronized Runnable getTask() throws InterruptedException {
while (workQuee.size() == 0) {
//当工作队列中的线程为0时,如果线程池关闭,则返回null.负责,等待任务
if (isClosed) {
return null;
} else {
wait();
}
}
return workQuee.removeFirst();//从工作队列中弹出第一个元素
} /**
* 关闭线程池
*/
public synchronized void closed() {
//线程池没有关闭
if (!isClosed) {
isClosed = true;
workQuee.clear();//清除工作队列
interrupt();//中断所有的线程
}
} /**
* 等在工作线程将若有的任务执行完毕
*/
public void join() {
synchronized (this) {
isClosed = true;
notifyAll();//唤醒所有的等待任务的工作线程
}
//activeCount() 返回此线程组中活动线程的估计数。 来自ThreadGroup
Thread[] threads = new Thread[activeCount()];
// enumerate[list] 把此线程组及其子组中的所有活动线程复制到指定数组中。
int count = enumerate(threads);//返回所有的活着的线程数量
for (int i = 0; i < count; i++) {
try {
threads[i].join();//等待所有的活动的工作宣称的结束
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} /**
* 内部类,创建的工作线程对象
*/
private class WorkThread extends Thread {
public WorkThread() {
super(ThreadPool.this, "WorkThread-" + workThreadID++);
} @Override public void run() {
//线程没有中断
while (!isInterrupted()) {
Runnable task = null;
try {
task = getTask();//获取任务
} catch (InterruptedException e) {
e.printStackTrace();
}
if (task == null) {
return;
}
try {
task.run();//运行任务
} catch (Throwable t) {
t.printStackTrace();
} }
}
}
}
1 流程执行的分析:

关注两个成员变量:
1> isClosed---->表示线程池是否关闭;workQuee:表示的工作队列,使用的类型是LinkedList.
2> 在构造器中初始化工作队列,然后启动每一个线程;
3>execute()方法的执行如下所示:线程池对象的核心就是将线程添加到工作队列中
4>getTask()方法 从工作队列中获取线程
5> closed()方法:关闭线程池
6>join()方法;等待线程执行完所有的任务

2 测试自定义线程池:
package com.asiaInfo.caozg.ch_03.threadPool; import static java.lang.Integer.parseInt; /**
* @Authgor: gosaint
* @Description:
* @Date Created in 16:25 2018/3/2
* @Modified By:线程池测试
*/
public class ThreadPoolTester { public static void main(String[] args) {
if (args.length != 2) {
System.out.println(
"用法: java ThreadPoolTest numTasks poolSize");
System.out.println(
" numTasks - integer: 任务的数目");
System.out.println(
" numThreads - integer: 线程池中的线程数目");
return;
}
int numTasks = Integer.parseInt(args[0]);
int poolSize = Integer.parseInt(args[1]); ThreadPool threadPool = new ThreadPool(poolSize); //创建线程池 // 运行任务
for (int i = 0; i < numTasks; i++)
threadPool.execute(createTask(i)); threadPool.join(); //等待工作线程完成所有的任务
// threadPool.close(); //关闭线程池
}//#main() /**
* 定义了一个简单的任务(打印ID)
*/
private static Runnable createTask(final int taskID) {
return new Runnable() {
public void run() {
System.out.println("Task " + taskID + ": start");
try {
Thread.sleep(500); //增加执行一个任务的时间
} catch (InterruptedException ex) {
}
System.out.println("Task " + taskID + ": end");
}
};
}
}
设置参数5,3.表示5个任务3个线程去执行:

使用线程池优化Echo模型的更多相关文章
- java笔记--使用线程池优化多线程编程
使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库 ...
- Mysql线程池优化笔记
Mysql线程池优化我是总结了一个站长的3篇文章了,这里我整理到一起来本文章就分为三个优化段了,下面一起来看看. Mysql线程池系列一(Thread pool FAQ) 首先介绍什么是mys ...
- 使用自定义线程池优化EchoServer
在上一篇文章中http://www.cnblogs.com/gosaint/p/8494423.html 我自定义了线程池ThreadPool.现在在我的EchoServer中使用自定义线程池去负责和 ...
- 线程锁,threadinglocal,线程池,生产者消费者模型
1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...
- Dubbo学习笔记8:Dubbo的线程模型与线程池策略
Dubbo默认的底层网络通讯使用的是Netty,服务提供方NettyServer使用两级线程池,其中 EventLoopGroup(boss) 主要用来接受客户端的链接请求,并把接受的请求分发给 Ev ...
- MYSQL线程池总结(一)
线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...
- MySQL具体解释(7)-----------MySQL线程池总结(一)
线程池是Mysql5.6的一个核心功能.对于server应用而言,不管是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发訪问时,一定伴随着资源的不断创建和释放.导致资源利 ...
- (转)MYSQL线程池总结(一)
MYSQL线程池总结(一) 原文:http://www.cnblogs.com/cchust/p/4510039.html 线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应 ...
- MySQL线程池总结
线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...
随机推荐
- jsp:jstl标签forTokens
forTokens 标签这个标签的作用和 Java 中的 StringTokenizer 类的作用非常相似,它通过 items 属性来指定一个特定的字符串,然后通过 delims 属性指定一种分隔符( ...
- hdu 3401 单调队列优化+dp
http://acm.hdu.edu.cn/showproblem.php?pid=3401 Trade Time Limit: 2000/1000 MS (Java/Others) Memor ...
- MySql按周/月/日分组统计数据的方法
知识关键词:DATE_FORMAT select DATE_FORMAT(create_time,'%Y%u') weeks,count(caseid) count from tc_case grou ...
- linux 部署nginx----端口转发
一.解压安装 tar zxvf nginx-.tar.gz cd nginx- ./configure --with-http_stub_status_module --with-http_ssl_m ...
- Codeforces Round #254(div2)A
很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“- ...
- maven module开发 自动打包
http://blog.csdn.net/u011113713/article/details/52413903 http://blog.csdn.net/sisyphus_z/article/det ...
- myEclipse下Maven配置操作
一.Maven 安装与配置 1.点击计算机属性里的高级系统设置,点开环境变量进行配置 2.检验配置是否成功 二.手动创建一个Maven项目,并编译运行成功 1.创建一个文件夹作为项目的根目录 2. 在 ...
- Java 参数的和
public class CommandParamter { public static void main(String[] args) { // TODO Auto-generated metho ...
- Django 登录页面重定向
转自:http://blog.chedushi.com/archives/3484 登陆和注销操作在网页编程上很常见,这两个操作经常需要在操作成功以后转入发出请求的页面. 比如用户正在浏览一篇文章,发 ...
- C#面向对象(二):封装和继承
前文链接:C#面向对象(一):明确几个简单的概念作为开胃菜 面向对象开发有三大特性(特点 / 特征) : 封装, 继承, 多态.我们今天主要讨论封装和继承,多态会在下篇中讨论. 一.封装: 所谓封装, ...