Java线程池技术以及实现
对于服务端而言,经常面对的是客户端传入的短小任务,需要服务端快速处理并返回结果。如果服务端每次接受一个客户端请求都创建一个线程然后处理请求返回数据,这在请求客户端数量少的阶段看起来是一个不错的选择,但是面对成千上万的请求在某一时段同时到达服务器时,如果还是采用这种方式,那么将会创建数以万计的线程,暂且不讨论线程是否会达到操作系统上限,单单操作系统频繁的进行线程的上下文切换就是一个巨大的开销,无故的增加的系统的负载,而线程的创建和消亡都是需要耗费系统资源的,也无疑造成了资源的浪费。
线程池技术就能很好的解决这个问题,它事先创建好了若干个处理请求任务的线程,线程的数量并不受请求客户端的控制,在这前提下使用固定或者较为固定数目的线程来完成请求任务的处理,消除了频繁创建和消亡线程的系统资源开销。
下面定义一个简单的线程池接口 :
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线程池技术以及实现的更多相关文章
- java线程池技术(二): 核心ThreadPoolExecutor介绍
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...
- java线程池技术
1.线程池的实现原理?简介: 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- java线程池技术(一):ThreadFactory与BlockingQueue
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.ThreadFactory概述以及源码分析 ThreadFactory很简单,就是一个线程工厂也就是负责生产线程的,我们看下ThreadFact ...
- java线程池系列(1)-ThreadPoolExecutor实现原理
前言 做java开发的,一般都避免不了要面对java线程池技术,像tomcat之类的容器天然就支持多线程. 即使是做偏后端技术,如处理一些消息,执行一些计算任务,也经常需要用到线程池技术. 鉴于线程池 ...
- Java基础-Java中的并法库之线程池技术
Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.
- 池化技术之Java线程池
https://blog.csdn.net/jcj_2012/article/details/84906657 作用 线程池,通过复用线程来提升性能; 背景 线程是一个操作系统概念.操作系统负责这个 ...
- 深度分析:Java并发编程之线程池技术,看完面试这个再也不慌了!
线程池的好处 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池,相对于单线程串行处理(Serial Processing ...
- Java 线程池的原理与实现
最近在学习线程池.内存控制等关于提高程序运行性能方面的编程技术,在网上看到有一哥们写得不错,故和大家一起分享. 建议:在阅读本文前,先理一理同步的知识,特别是syncronized同步关键字的用法.关 ...
- Java线程池的实现
线程池的作用: 一个线程的周期分为:创建.运行.销毁三个阶段. 处理一个任务时,首先创建一个任务线程,然后执行任务,完了还要销毁线程.而线程只有处于运行状态的时候,才是真的在处理我们交给它的任务,这个 ...
随机推荐
- Revolving Digits
题面 [题目描述]: 有一天,Silence对可以旋转的正整数十分感兴趣.在旋转操作中,他可以把后面的数字按照原位置不动地搬到剩下位置的前面.当然,他也可以完全不动这串数字.比如,他可以把123变为1 ...
- 【Protocol Buffers】grpc默认使用的Google 开源的一套成熟的结构数据序列化机制
grpc默认使用的Google 开源的一套成熟的结构数据序列化机制 参考地址:https://blog.csdn.net/shensky711/article/details/69696392 参考地 ...
- android_浅析canvas的save()和restore()方法
<span style="font-size:18px;"> </span> <span style="font-size:18px;&qu ...
- EasyMvc入门教程-基本控件说明(9)引言导航
休息片刻后,继续开工... 这次我们继续学习引言导航,引言导航主要用于知识点的开始,起到知识点导航的作用.直接例子: 实现代码如下: @Html.Q().BlockRef().Title(" ...
- iOS7系统中的坑——UITableViewCellScrollView
今天开完一系列例会后,终于迎来放假的时候了,本来中午就要下班走的,想着火车票现在还很早,也就不急着走,闲着无聊,想着之前要写的内容,索性写一篇聊以打发时光,也希望对其他人有所帮助吧. 现在iOS的最新 ...
- yarn 基本用法
1.初始化一个新的项目 yarn init 2.添加一个依赖包 yarn add [package] yarn add [package]@[version] yarn add [package]@[ ...
- C语言变长数组 struct中char data[0]的用法
版权声明:本文为博主原创文章,未经博主允许不得转载. 今天在看一段代码时出现了用结构体实现变长数组的写法,一开始因为忘记了这种技术,所以老觉得作者的源码有误,最后经过我深思之后,终于想起以前看过的用s ...
- Unity3D总结:关于射线碰撞
方法一:Physics.Raycast 光线投射 1.static function Raycast (origin : Vector3, direction : Vector3, distance ...
- angularJS 常用插件指令
长时间没有登入博客园了,今天突然想了想,当初开这个的目的,其实就是为了记录你当下的一个状态和累计一些问题,所以记录这些还是很有意义,毕竟不是什么牛,靠脸又吃不饱的这个年代,需要留下一些东西给自己看也好 ...
- Apache Server与多个独立Tomcat集成
取经自http://www.ramkitech.com/2012/03/virtual-host-apache-httpd-server-tomcat.html 继续干Tomcat和Apache Se ...