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

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

  

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

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. [simple-orm-mybaits]基于Mybatis的ORM封装介绍

    目录 前言 ORM框架现状 Mybatis优缺点 simple-orm-mybatis设计思路介绍 simple-orm-mybatis使用说明 simple-orm-mybatis实际使用 推荐最佳 ...

  2. K-L变换和 主成分分析PCA

    一.K-L变换 说PCA的话,必须先介绍一下K-L变换了. K-L变换是Karhunen-Loeve变换的简称,是一种特殊的正交变换.它是建立在统计特性基础上的一种变换,有的文献也称其为霍特林(Hot ...

  3. 20. Spring Boot Servlet【从零开始学Spring Boot】

    转载:http://blog.csdn.net/linxingliang/article/details/52069482 Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可 ...

  4. 百科知识 .e,.ec文件如何打开

    1 .e是易语言源文件,你可以从以下网址下载e语言编程环境: http://www.xiazaiba.com/html/409.html   2 安装之后会自动关联.e文件.   3 打开一个e语言文 ...

  5. Odoo(OpenERP)开发实践:通过XML-RPC接口訪问Odoo数据库

    Odoo(OpenERP)server支持通过XML-RPC接口訪问.操作数据库,基于此可实现与其它系统的交互与集成. 本文是使用Java通过XMLRPC接口操作Odoo数据库的简单演示样例.本例引用 ...

  6. C 标准库 - <float.h>

    C 标准库 - <float.h> 简介 C 标准库的 float.h 头文件包含了一组与浮点值相关的依赖于平台的常量.这些常量是由 ANSI C 提出的,这让程序更具有可移植性.在讲解这 ...

  7. 小数运算需要注意什么? 接口和抽象类 WinForm窗体上两个panel,怎么实现一个panel固定漂浮在另一个panel之上

    小数运算需要注意什么? 1. 生活中0.1+0.2=0.3, 计算机中可不是这样,为什么呢? 大家都知道计算机类型都是有数据范围的.整形int范围是 正负21亿左右,小数类型同样也是有范围的,但是即使 ...

  8. php自定义错误

    function myErrorHandler ( $errno , $errstr , $errfile , $errline ) { if (!( error_reporting () & ...

  9. Windows socket I/O模型 之 select(2)

    在Windows socket I/O模型 之  select(1)中.我们仅仅是在console中简单的模拟了select的处理方法. 还有非常多特性不能改动.比方仅仅能写,不能读. 没使用线程.也 ...

  10. 实习日记 laravel怎么删除磁盘上的文件

    Storage 里面有 delete的方法 具体使用是 Storage::disk('uploads')->delete($fileName); 其中'uploads'是filesystem里面 ...