多线程系列之九:Worker Thread模式
一,Worker Thread模式
也叫ThreadPool(线程池模式)
二,示例程序
情景:
一个工作车间有多个工人处理请求,客户可以向车间添加请求。
请求类:Request
定义了请求的信息和处理该请求的方法
车间类:Channel
定义了车间里的工人,存放请求的容器。接收请求的方法,处理完请求后取出请求的方法
客户类:ClientThread
创建请求,并把请求交给车间
工人类:WorkerThread
处理请求
public class Request {
private final String name;
private final int number;
private static final Random random = new Random();
public Request(String name,int number){
this.name = name;
this.number = number;
}
/**
* 处理该请求的方法
*/
public void execute(){
System.out.println(Thread.currentThread().getName()+" executes "+this);
try {
Thread.sleep(random.nextInt(1000));
}catch (InterruptedException e){
}
}
@Override
public String toString() {
return " [ Request from "+ name + " NO." +number+" ] ";
}
}
public class Channel {
private static final int MAX_REQUEST = 100 ;
private final Request[] requestQueue;
private int tail;
private int head;
private int count;
private final WorkerThread[] threadPool;
public Channel(int threads){
this.requestQueue = new Request[MAX_REQUEST];
this.head = 0;
this.tail = 0;
this.count = 0;
threadPool = new WorkerThread[threads];
for (int i = 0; i < threadPool.length; i++) {
threadPool[i] = new WorkerThread("Worker-"+i,this);
}
}
/**
* 启动线程
*/
public void startWorkers(){
for (int i = 0; i < threadPool.length; i++) {
threadPool[i].start();
}
}
/**
* 接受请求
* @param request
*/
public synchronized void putRequest(Request request){
while (count >= requestQueue.length){
try{
wait();
}catch (InterruptedException e){
}
}
requestQueue[tail] = request;
tail = (tail + 1)%requestQueue.length;
count++;
notifyAll();
}
public synchronized Request takeRequest(){
while (count <= 0){
try {
wait();
}catch (InterruptedException e){
}
}
Request request = requestQueue[head];
head = (head + 1)%requestQueue.length;
count--;
notifyAll();
return request;
}
}
public class ClientThread extends Thread {
private final Channel channel;
private static final Random random = new Random();
public ClientThread(String name,Channel channel){
super(name);
this.channel = channel;
}
@Override
public void run() {
try {
for (int i = 0; true ; i++) {
Request request = new Request(getName(),i);
channel.putRequest(request);
Thread.sleep(random.nextInt(1000));
}
}catch (InterruptedException e){
}
}
}
public class WorkerThread extends Thread{
private final Channel channel;
public WorkerThread(String name,Channel channel){
super(name);
this.channel = channel;
}
@Override
public void run() {
while (true){
Request request = channel.takeRequest();
request.execute();
}
}
}
public class Test {
public static void main(String[] args) {
Channel channel = new Channel(5);
channel.startWorkers();
new ClientThread("aaa",channel).start();
new ClientThread("bbb",channel).start();
new ClientThread("ccc",channel).start();
}
}
三,使用场景
1,提高吞吐量
由于启动新线程需要花费时间,所以这个模式可以通过轮流反复的使用线程来提高吞吐量
2,容量控制
可以控制工人的数量(控制同时处理请求的线程的数量)
3,调用和执行的分离 (类似消息中间件)
Client角色负责发送工作请求,Worker角色负责处理请求。将方法的调用和执行分离开来
这样可以提高响应速度,调用方执行完后不必等待执行方,调用完成后可以做别的事情
四,通过java.util.concurrent包创建线程池
public class Request17 implements Runnable {
private final String name;
private final int number;
private static final Random random = new Random();
public Request17(String name,int number){
this.name = name;
this.number = number;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" executes "+this);
try {
Thread.sleep(random.nextInt(1000));
}catch (InterruptedException e){
}
}
@Override
public String toString() {
return " [ Request from "+ name + " NO." +number+" ] ";
}
}
public class ClientThread17 extends Thread {
private final ExecutorService executorService;
private static final Random random = new Random();
public ClientThread17(String name,ExecutorService executorService){
super(name);
this.executorService = executorService;
}
@Override
public void run() {
try {
for (int i = 0; true ; i++) {
Request17 request17 = new Request17(getName(),i);
executorService.execute(request17);
Thread.sleep(1000);
}
}catch (InterruptedException e){
}catch (RejectedExecutionException e){
System.out.println(getName()+ " : "+ e);
}
}
}
public class Test17 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
try {
new ClientThread17("aaa",executorService).start();
new ClientThread17("bbb",executorService).start();
new ClientThread17("ccc",executorService).start();
Thread.sleep(5000);
}catch (InterruptedException e){
}finally {
//主线程执行大约5秒后,关闭线程池。关闭线程池后,execute方法会被拒绝执行,并抛出异常 RejectedExecutionException异常啊
executorService.shutdown();
}
}
}
多线程系列之九:Worker Thread模式的更多相关文章
- Java Thread系列(九)Master-Worker模式
Java Thread系列(九)Master-Worker模式 Master-Worker模式是常用的并行设计模式. 一.Master-Worker 模式核心思想 Master-Worker 系统由两 ...
- 多线程 Worker Thread 模式
Worker是“工人”的意思,worker thread pattern中,工人线程(worker thread)会一次抓一件工作来处理,当没有工作可做时,工人线程会停下来等待心得工作过来. Work ...
- Java 设计模式系列(九)组合模式
Java 设计模式系列(九)组合模式 将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象的使用具有一致性. 一.组合模式结构 Component: 抽象 ...
- Worker Thread模式
工人线程Worker thread会逐个取回工作并进行处理,当所有工作全部完成后,工人线程会等待新的工作到来 5个工人线程从传送带取数据,3个传送工人线程将数据放入传送带 public class C ...
- java多线程系列15 设计模式 生产者 - 消费者模式
生产者-消费者 生产者消费者模式是一个非常经典的多线程模式,比如我们用到的Mq就是其中一种具体实现 在该模式中 通常会有2类线程,消费者线程和生产者线程 生产者提交用户请求 消费者负责处理生产者提交的 ...
- 多线程系列之十:Future模式
一,Future模式 假设有一个方法需要花费很长的时间才能获取运行结果.那么,与其一直等待结果,不如先拿一张 提货单.获取提货单并不耗费时间.这里提货单就称为Future角色获取Future角色的线程 ...
- 多线程系列之七:Read-Write Lock模式
一,Read-Write Lock模式 在Read-Write Lock模式中,读取操作和写入操作是分开考虑的.在执行读取操作之前,线程必须获取用于读取的锁.在执行写入操作之前,线程必须获取用于写入的 ...
- 多线程系列之四:Guarded Suspension 模式
一,什么是Guarded Suspension模式如果执行现在的处理会造成问题,就让执行处理的线程等待.这种模式通过让线程等待来保证实例的安全性 二,实现一个简单的线程间通信的例子 一个线程(Clie ...
- java多线程系列 目录
Java多线程系列1 线程创建以及状态切换 Java多线程系列2 线程常见方法介绍 Java多线程系列3 synchronized 关键词 Java多线程系列4 线程交互(wait和 ...
随机推荐
- 阿里云windows2012+iis8配置https
第一步先创建一个免费的证书 步骤一:申请免费证书 步骤二:填写你的二级域 步骤三:等待审核通过,通过后,点击下载 步骤四:根据自己服务器类型,下载对应的证书,根据阿里云的安装步骤做 以下是阿里云提供的 ...
- spring boot +RabbitMQ +InfluxDB+Grafara监控实践
本文需要有相关spring boot 或spring cloud 相关微服务框架的基础,如果您具备相关基础可以很容易的实现下述过程!!!!!!! 希望本文的所说对需要的您有所帮助 从这里我们开始进入闲 ...
- 聚类——K-means
聚类——认识K-means算法 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 一.聚类与分类 聚类: 无监督学习.聚类是在预先不知道欲划分类的情况下, ...
- Java strictfp
strictfp关键字 用于强制Java中的浮点计算(float或double)的精度符合IEEE 754标准. 不使用strictfp:浮点精度取决于目标平台的硬件,即CPU的浮点处理能力. 使用s ...
- ubuntu 环境下编译 hadoop 2.6.0的简单方法
由于服务器一般都64位系统, hadoop网站的release版本32位native库不能运行,所以需要自己在编译一下.以下是我采用的一个编译的过程,比较简单,不用下载各种版本及环境配置,通过命令就能 ...
- linux 软连接创建 压缩解压缩 linux的dns服务相关
linux软连接创建 注意用绝对路径,语法如下 ln -s 目标文件绝对路径 软连接名字绝对路径 ln -s /小护士.txt /tmp/hs.txt 修改linux的PS1变量,命令提示符变量 PS ...
- mysql数据权限的分配
在我们使用mysql数据库时,有时我们的程序与数据库不在同一机器上,这时我们需要远程访问数据库.缺省状态下,mysql的用户没有远程访问的权限. 下面介绍两种方法,解决这一问题. 1.改表法 可能是你 ...
- 深度学习框架PyTorch一书的学习-第六章-实战指南
参考:https://github.com/chenyuntc/pytorch-book/tree/v1.0/chapter6-实战指南 希望大家直接到上面的网址去查看代码,下面是本人的笔记 将上面地 ...
- CF650C Table Compression
CF650C Table Compression 给一个 \(n\times m\) 的非负整数矩阵 \(a\),让你求一个 \(n\times m\) 的非负整数矩阵 \(b\),满足以下条件 若 ...
- js 原生ajax实现
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...