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

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

  

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

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. Java Web工程连接MySQL数据库及Tomcat服务器页面中文乱码

    Java Web工程连接MySQL数据库 一. 准备工作 1.下载连接MySQL数据库的JDBC (可以去官网下,也可以去百度云找) 2.将下载的jar文件复制到Tomcat的lib目录下 3.新建一 ...

  2. 【maven】Maven将中央仓库修改为阿里云的仓库地址

    <mirror> <id>nexus-aliyun</id> <mirrorOf>*</mirrorOf> <name>Nexu ...

  3. Activiti 流程部署方式 activi 动态部署(高级源代码篇)

    Activiti的流程 部署方式有非常多种方式,我们能够依据activit工作流引擎提供的ap方式进行部署. 当然了实际需求决定你要使用哪一种api操作,后面的总结具体介绍了使用场景. 以下看一下部署 ...

  4. ZooKeeper 授权验证

    ZooKeeper 授权验证 学习了:https://blog.csdn.net/liuyuehu/article/details/52121755 zookeeper可以进行认证授权:

  5. 怎样高速启动Android模拟器(Android Emulator)

    总所周知,每次我们启动Android Emulator,都须要花费非常长一段时间,几分钟甚至十几分钟.事实上,我们能够使用快照(Snapshot)功能,来高速启动Android模拟器. 首先.须要在A ...

  6. C# Http方式下载文件到本地

    下文代码是从网络(http://www.cnblogs.com/hayden/archive/2012/04/26/2472815.html)得来,亲测好用.我中修改了下格式和注释,版权属于原作者“舒 ...

  7. Spring学习资料

    1.马士兵视频 2.SPRING技术内幕__深入解析SPRING架构与设计原理 3.jinnianshilongnian博客 4.Spring实战 (Spring IN Action) 5.官方文档

  8. pjblog支持QQ、新浪微博一键登录

    转载地址: http://www.ruisoftcn.com/blog/article.asp?id=955

  9. 关于mongodb副本集读写分离 及 日志切换

    mongodb的读写分离使用Replica Sets来实现 对于replica set 中的secondary 节点默认是不可读的.在写多读少的应用中,使用Replica Sets来实现读写分离.通过 ...

  10. Java中Class.forName()的作用(转载)

    http://www.360doc.com/content/10/0712/10/1720440_38421273.shtml# 使用jdbc方式连接数据库时会使用一句代码Class.forName( ...