对于服务端而言,经常面对的是客户端传入的短小任务,需要服务端快速处理并返回结果。如果服务端每次接受一个客户端请求都创建一个线程然后处理请求返回数据,这在请求客户端数量少的阶段看起来是一个不错的选择,但是面对成千上万的请求在某一时段同时到达服务器时,如果还是采用这种方式,那么将会创建数以万计的线程,暂且不讨论线程是否会达到操作系统上限,单单操作系统频繁的进行线程的上下文切换就是一个巨大的开销,无故的增加的系统的负载,而线程的创建和消亡都是需要耗费系统资源的,也无疑造成了资源的浪费。

  线程池技术就能很好的解决这个问题,它事先创建好了若干个处理请求任务的线程,线程的数量并不受请求客户端的控制,在这前提下使用固定或者较为固定数目的线程来完成请求任务的处理,消除了频繁创建和消亡线程的系统资源开销。

  

  下面定义一个简单的线程池接口 :

public interface ThreadPool<Task extends Runnable> {

    //执行一个Task,这个Task需要实现Runnable
void execute(Task task) ; //关闭线程池
void shutdown() ; //增加工作线程
void addWorker(int num ) ; //减少工作线程
void removeWorker(int num); //得到正在执行的任务数量
int getTaskSize() ; }

  客户端可以通过execute(Task)方法将Task提交入线程池执行,而客户端自身不用等待Task的执行完成。线程池还提供了增加/减小工作线程以及关闭线程池的方法,这里的工作线程就代表了一个重复执行Task的线程,而每个由客户端提交的Task都将进入到一个等待队列中等待工作线程处理。

  接下来是线程池接口的默认实现 :

public class DefaultThreadPool<Task extends Runnable> implements ThreadPool<Task> {

    //线程池最大限制数
private static final int MAX_WORKER_NUMBERS = 10;
//线程池默认的数量
private static final int DEFAULT_WORKER_NUMBERS= 5;
//线程池最小数量
private static final int MIN_WORKER_NUMBERS = 1 ;
//这是一个任务列表,将会向里面插入任务
private final LinkedList<Task> jobs = new LinkedList<Task>() ;
// 工作者列表
private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>()) ;
//工作者线程的数量
private int workerNum = DEFAULT_WORKER_NUMBERS ;
//线程编号生成
private AtomicLong threadNum = new AtomicLong() ; public DefaultThreadPool(){
initializeWorkers(DEFAULT_WORKER_NUMBERS);
}
public DefaultThreadPool(int initSize){
workerNum = initSize > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS :
initSize < MIN_WORKER_NUMBERS ?MIN_WORKER_NUMBERS : initSize ;
initializeWorkers(workerNum);
} private void initializeWorkers(int num){
for(int i = 0 ; i < num ; i++){
Worker worker = new Worker() ;
workers.add(worker) ;
Thread t = new Thread(worker, "ThreadPool-worker-"+threadNum.incrementAndGet()) ;
t.start();
}
} @Override
public void execute(Task task) {
if(task!=null){
synchronized(jobs){
jobs.addLast(task);
//通知
jobs.notify();
}
}
} @Override
public void shutdown() {
for(Worker worker : workers){
worker.shutdown();
}
} @Override
public void addWorker(int num) {
//这里是否应该选择workers为监视器锁
synchronized(workers){
//判断新增的数量是否超出线程池的内置规则
if(num+this.workerNum > MAX_WORKER_NUMBERS){
num = MAX_WORKER_NUMBERS - this.workerNum ;
}
initializeWorkers(num);
this.workerNum += num ;
}
} @Override
public void removeWorker(int num) {
synchronized(workers){
if(num >= this.workerNum){
throw new IllegalArgumentException("beyond workNum") ;
} for(int i = 0 ; i < num ; i++){
Worker worker = workers.get(i);
if(workers.remove(worker)){
worker.shutdown();
}
}
this.workerNum -=num ;
}
} @Override
public int getTaskSize() { return jobs.size();
} class Worker implements Runnable{
private volatile boolean running ;
@Override
public void run() {
while(running){ Task job = null ;
synchronized(jobs){
//如果任务列表是空的,那么就wait
if(jobs.isEmpty()){
try {
jobs.wait();
} catch (InterruptedException e) {
//感知到外部对WorderThread的中断操作。返回
Thread.currentThread().interrupt();
return ;
}
}
job = jobs.removeFirst() ;
} if(job!=null){
try {
job.run();
} catch (Exception e) {
//忽略job执行中的exception
}
}
}//while end
}//run end
public void shutdown(){
running = false ;
}
}
}

Java线程池技术以及实现的更多相关文章

  1. java线程池技术(二): 核心ThreadPoolExecutor介绍

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...

  2. java线程池技术

    1.线程池的实现原理?简介: 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  3. java线程池技术(一):ThreadFactory与BlockingQueue

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.ThreadFactory概述以及源码分析 ThreadFactory很简单,就是一个线程工厂也就是负责生产线程的,我们看下ThreadFact ...

  4. java线程池系列(1)-ThreadPoolExecutor实现原理

    前言 做java开发的,一般都避免不了要面对java线程池技术,像tomcat之类的容器天然就支持多线程. 即使是做偏后端技术,如处理一些消息,执行一些计算任务,也经常需要用到线程池技术. 鉴于线程池 ...

  5. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  6. 池化技术之Java线程池

     https://blog.csdn.net/jcj_2012/article/details/84906657 作用 线程池,通过复用线程来提升性能; 背景 线程是一个操作系统概念.操作系统负责这个 ...

  7. 深度分析:Java并发编程之线程池技术,看完面试这个再也不慌了!

    线程池的好处 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池,相对于单线程串行处理(Serial Processing ...

  8. Java 线程池的原理与实现

    最近在学习线程池.内存控制等关于提高程序运行性能方面的编程技术,在网上看到有一哥们写得不错,故和大家一起分享. 建议:在阅读本文前,先理一理同步的知识,特别是syncronized同步关键字的用法.关 ...

  9. Java线程池的实现

    线程池的作用: 一个线程的周期分为:创建.运行.销毁三个阶段. 处理一个任务时,首先创建一个任务线程,然后执行任务,完了还要销毁线程.而线程只有处于运行状态的时候,才是真的在处理我们交给它的任务,这个 ...

随机推荐

  1. spring springmvc js websocket 监听

    第一步:web.xml中支持异步.所有的filter及servlet <filter> <filter-name>characterEncoding</filter-na ...

  2. windows XP 下的DTRACE 跟踪 学习

    https://github.com/prash-wghats/DTrace-win32 1. dtrace_loader.exe -l //to load dtrace drivers 2. C:\ ...

  3. MFC改变控件颜色

    from http://www.cppblog.com/FandyM/archive/2010/07/21/120972.aspx MFC应用程序中,要改变控件的背景色可通过重载OnCtlColor( ...

  4. Spring IOC知识java反射

    [1] Java反射知识-->Spring IoC :http://www.iteye.com/topic/1123081 [2] Java动态代理-->Spring AOP :http: ...

  5. squirrelsql安装

    官网下载安装,第一次安装mac上,失败,后续重启mac看下.重启完后,还是起不来,估计和某些环境冲突,或者缺少环境 使用squirrelsql如何连接hive? http://lxw1234.com/ ...

  6. AngularJS:实现动态添加输入控件功能

    功能要求如下:1.    点击加号可以增加输入框.2.    点击减号可以减少输入框.3.    当输入框只有一个的时候,不能再减少输入框.效果图如下:只有一个输入框有多个输入框 要实现这个功能,可以 ...

  7. chm 转 pdf 工具推荐与对比

    在进行推荐chm转pdf的软件之前,首先来了解一下为什么我们要将chm转为pdf. CHM是英语“Compiled Help Manual”的简写,即“已编译的帮助文件”.CHM是微软新一代的帮助文件 ...

  8. valid-palindrome——判断带符号数字字母的字符串是否为回文

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  9. python(5)- 简单练习:python三级菜单优化

    python三级菜单优化,菜鸟版链接:http://www.cnblogs.com/xuyaping/p/6648170.html menu = { '北京':{ '海淀':{ '五道口':{ 'so ...

  10. 封装PDO操作数据库

    <?php class DatabaseHandler { /** * sql语句查询 */ public static function query_data ($dataName,$sql, ...