在上一篇文章中 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. mysql性能优化之索引优化

    作为免费又高效的数据库,mysql基本是首选.良好的安全连接,自带查询解析.sql语句优化,使用读写锁(细化到行).事物隔离和多版本并发控制提高并发,完备的事务日志记录,强大的存储引擎提供高效查询(表 ...

  2. svn默认地址老发生改变,记下默认路径

    C:\Users\Administrator\AppData\Roaming\Subversion

  3. nyoj-1016-德莱联盟(向量叉乘判断线段相交)

    叉乘的坐标表示: A(X1,Y1), B(X2, Y2), C(XC,YC), D(XD, YD);AB = (X2-X1, Y2-Y1);CD = (XD-XC, YD-YC); 向量AB,CD的叉 ...

  4. 树莓派视频监控 —— 使用 mjpg

    下载到树莓派本地: $ wget https://github.com/jacksonliam/mjpg-streamer/archive/master.zip $ unzip master.zip ...

  5. 使用PHP配置文件

    /**************************************************************************************** * 使用PHP配置文 ...

  6. Java演示手机发送短信验证码功能实现

    我们这里采用阿里大于的短信API 第一步:登陆阿里大于,下载阿里大于的SDK a.在阿里大于上创建自己的应用 b.点击配置管理中的验证码,先添加签名,再配置短信模板 第二步:解压相关SDK,第一个为j ...

  7. idea 创建maven工程(入门)

    转:http://blog.csdn.net/qq_32588349/article/details/51461182 1. 下载Maven 官方地址:http://maven.apache.org/ ...

  8. Sqoop-从hive导出分区表到MySQL

    经多次验证,发现并没有特殊的方法能够直接把多个分区一次性读入,并插入MySQL的方法,以后发现会在此添加. Sqoop只提供了从MySQL导入到HIVE分区表的相关参数,反向并无特别参数. 从HIVE ...

  9. BZOJ4605:崂山白花蛇草水

    浅谈\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html 题目传送门:https://lydsy.com/JudgeOnline ...

  10. 异常[PersistenceUnit: default] Unable to build Hibernate SessionFactory

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManage ...