在上一篇文章中 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. C++(十四) — 常用快捷键总结

      快捷键设置方法:https://blog.csdn.net/wrzfeijianshen/article/details/53230789 https://blog.csdn.net/wrzfei ...

  2. 性能差异 ASP.NET WebForm与ASP.NET MVC

    一.为什么说 ASP.NET WebForm 比 ASP.NET MVC 要差? WebForm 顾名思义,微软一向主打简单化,窗体模式,拖拽控件就能做网站了, 然而这也引发了许多 Java 和 .N ...

  3. MySQL 分区知识点(一 )

    前言: 查了下资料,关于 MySQL 分区的博文讲的详细的比较少,也不全,只好在官网去翻译英文文章看了.大体整理了一下记录起来: MySQL 分区类型: 1.RANGE 分区: // 这种类型的分区基 ...

  4. linux 部署nginx----端口转发

    一.解压安装 tar zxvf nginx-.tar.gz cd nginx- ./configure --with-http_stub_status_module --with-http_ssl_m ...

  5. mysql Replication机制

      从上图可以看见MySQL 复制的基本过程如下: Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容: Master 接收到来自 Sl ...

  6. 如何卸载Python通过setup.py安装的模块

    0,pip uninstall  xxxx     1.找到egg sudo easy_install -m BitVector .... Using /usr/local/lib/python2./ ...

  7. ACM学习历程—2016"百度之星" - 资格赛(Astar Round1)

    http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=690 A题: 给定字符串,求任意区间的Hash值. 根据题目给定的Hash方式,属 ...

  8. 开启 intel vt-d

    1.开机后按“DEL”或“F2”进入BIOS: 2.在Advanced选项页中找到System Agent Configuration并选择进入: 3.进入System Agent Configura ...

  9. 基于TCP协议 I/O多路转接(select) 的高性能回显服务器客户端模型

    服务端代码: myselect.c #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> ...

  10. Azure CLI的Query

    Azure CLI 2.0是基于Python的命令行.其命令直观,使用非常方便. 其输出有四种模式: --output -o : Output format. Allowed values: json ...