使用线程池优化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标签库 uri标签
与 URL 相关的标签主要是用来将其他文件包含进来,或者提供页面之间的重定位以及 URL 地址的生成.参数的输出等等.一般包括如下几个标签<c:import>标签:与传统 JSP 页面中的 ...
- 关于JAVA一些知识的了解
一.枚举类型 示例代码: public class EnumTest { public static void main(String[] args){ Size s=Size.SMALL; ...
- 格式化SQL和逆格式SQL
上篇说过SQLyog中的计算合适数据类型的功能,现在说下Navicat格式化SQL和逆格式化SQL 啥也不说了,一看图,一目了然,Beautify SQL(格式化,即变成最美的语句)和Minify S ...
- linux(ubuntu16.04)下安装和破解pycharm专业版
我用的linux 版本是ubuntu,查看版本命令是: lsb_release -a 因为学习Python爬虫,pycharm是Python很好用的IDE,但是专业版需要付费,所以开始安装: 首先在官 ...
- python3的map(),filter()和reduce()函数总结
这三个都是内置的常用高阶函数(Higher-order function),用法如下: map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把 ...
- 【剑指offer】删除链表中重复的节点,C++实现(链表)
0.简介 本文是牛客网<剑指offer>笔记. 1.题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针.例如,链表1-> ...
- Gym - 100502G Outing (强连通缩点+树形依赖背包)
题目链接 问题:有n个人,最多选k个,如果选了某个人就必须选他指定的另一个人,问最多能选多少个人. 将每个人所指定的人向他连一条单向边,则每一个点都有唯一的前驱,形成的图是个基环树森林,在同一个强连通 ...
- Java演示手机发送短信验证码功能实现
我们这里采用阿里大于的短信API 第一步:登陆阿里大于,下载阿里大于的SDK a.在阿里大于上创建自己的应用 b.点击配置管理中的验证码,先添加签名,再配置短信模板 第二步:解压相关SDK,第一个为j ...
- 1625 codevs数字金字塔
1625 数字金字塔 USACO 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 考虑在下面被显示的数字金字塔. 写 ...
- AfxExtractSubString 函数的相关问题
AfxExtractSubString函数的用法 注:本文系rainy8758原创,转载请注明出处:http://blog.hjenglish.com/rainy8758/articles/10109 ...