在上一篇文章中 http://www.cnblogs.com/gosaint/p/8492356.html         我阐述了使用线程为每一个客户端创建一个工作线程来负责任务的执行。但是会存在如下的问题

  1.   服务器创建线程开销很大,有可能服务器创建线程消耗资源要比单独的和客户端通信所消耗的资源要大
  2.   如果存在大量的线程要同时创建,那么存在的内存开销很大。可能导致服务器系统内存不够
  3. 线程之间的切换消耗了大量的资源

  创建线程池可以较少线程的创建和销毁的开销,并且根据实际情况动态的调整线程池的大小。

  (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模型的更多相关文章

  1. java笔记--使用线程池优化多线程编程

    使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库 ...

  2. Mysql线程池优化笔记

    Mysql线程池优化我是总结了一个站长的3篇文章了,这里我整理到一起来本文章就分为三个优化段了,下面一起来看看.     Mysql线程池系列一(Thread pool FAQ) 首先介绍什么是mys ...

  3. 使用自定义线程池优化EchoServer

    在上一篇文章中http://www.cnblogs.com/gosaint/p/8494423.html 我自定义了线程池ThreadPool.现在在我的EchoServer中使用自定义线程池去负责和 ...

  4. 线程锁,threadinglocal,线程池,生产者消费者模型

    1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...

  5. Dubbo学习笔记8:Dubbo的线程模型与线程池策略

    Dubbo默认的底层网络通讯使用的是Netty,服务提供方NettyServer使用两级线程池,其中 EventLoopGroup(boss) 主要用来接受客户端的链接请求,并把接受的请求分发给 Ev ...

  6. MYSQL线程池总结(一)

    线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...

  7. MySQL具体解释(7)-----------MySQL线程池总结(一)

    线程池是Mysql5.6的一个核心功能.对于server应用而言,不管是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发訪问时,一定伴随着资源的不断创建和释放.导致资源利 ...

  8. (转)MYSQL线程池总结(一)

    MYSQL线程池总结(一)  原文:http://www.cnblogs.com/cchust/p/4510039.html 线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应 ...

  9. MySQL线程池总结

    线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...

随机推荐

  1. 五一清北学堂培训之Day 3之DP

    今天又是长者给我们讲小学题目的一天 长者的讲台上又是布满了冰红茶的一天 ---------------------------------------------------------------- ...

  2. hdu 5237 Base64(模拟)

    Base64 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  3. NOIP模拟题 栅栏

    题目大意 给定一个$n\times m$的网格图,每次会选择一块矩形沿着网格线铺上栅栏,或者拆除之前铺的栅栏,或者询问两个格子能否不经过栅栏直接到达. 保证栅栏没有重叠或交叉,删去的栅栏删除前一定存在 ...

  4. linux大于2T的磁盘格式化

    fdisk默认只能格式小于2T的磁盘,我们经常会碰到大于2T的磁盘,我们不能fdisk 格式化. 我们得用parted 来的格式化 parted 命令可能没有,yum install -y parte ...

  5. 10个 NPM 使用技巧

    对于一个项目,常用的一些npm简单命令包含的功能有:初始化一个文件夹( npm init ),下载npm模块( npm install ),创建测试( npm tese ) 和自定义脚本( npm r ...

  6. AMD 规范

    AMD(异步模块定义)是为浏览器环境设计的,因为 CommonJS 模块系统是同步加载的,当前浏览器环境还没有准备好同步加载模块的条件. AMD 定义了一套 JavaScript 模块依赖异步加载标准 ...

  7. position:sticky属性测试

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. RabbitMQ在windows环境下的安装

    最近一直想入手一台电脑,作为linux服务器,由于经济状况也没有入手,现在就先介绍windows环境下安装rabbitMQ. RabbitMQ是什么 ? RabbitMQ是一个在AMQP基础上完整的, ...

  9. Quartz 定时任务(含Redis)

    一  定时任务基础: MQ:Message Queue消息队列服务器:MSMQ.ActiveMQ.Redis等项目任务:确定邮件的发送,重置密码的发送(发送可能会很慢,而且有可能还需要重试),用消息队 ...

  10. JAX-WS注解

    JAX-WS注解: javax.jws.WebService @WebService应用于类或者接口上面,该类便是一个对外访问WebService,默认情况里面所有的public方法都是可以对外提供访 ...