多线程系列之九: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和 ...
随机推荐
- 排序算法之快速排序的思想以及Java实现
1 基本思想 快速排序是在冒泡排序的基础上改进而来的,它是基于分治的思想.通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据 ...
- 修改mysql默认端口
最初,我将mysql端口改成了3307,现在需要将其改3306端口,已改好,做个记录 首先:借助资源监视器,找到对应的端口,查看对应的Pid,然后打开任务管理器,点击服务,找到对应的服务器,将其服务停 ...
- CSS 简介、 选择器、组合选择器
#CSS 装饰器引入<!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...
- element ui Angular学习笔记(一)
1.element ui安装 npm i --save element-angular 2.Angular-cli引入 引入后需要开启ElModule.forRoot(),也可以单独引入某个组件入El ...
- selenium 使用
selenium selenium:可以让浏览器完成相关自动化的操作 环境安装: pip install selenium 编码流程: 导包 创建某一款浏览器对象 制定相关的行为动作 from sel ...
- 设计模式のInterpreter Patern(解释器模式)----行为模式
一.问题产生背景 有一句话“小明和小龙是好朋友”,我想分析其中谁是人,我想分析他们的关系等多种需求,那么我们应该如何处理,如果为每一个关系都进行判断?显然不合适,我们可以将二者的关系进行抽象处理,然后 ...
- 鼠标右键打开命令行cmd(管理员身份)
参考:https://blog.csdn.net/bdss58/article/details/54745380 添加到注册表 将下面命令保存为reg文件: Windows Registry Edit ...
- 解决y7000笔记本ubuntu下wifi无法连接问题
查看wifi与蓝牙硬件开关,发现ideapad的硬件模块都是关闭的 rfkill list all 打开终端 输入 sudo gedit /etc/rc.local 写入以下内容 进行保存 #!/bi ...
- spring jwt springboot RESTful API认证方式
RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authentication)和授权(Authorization)过程,保证API的安全性. Authenticatio ...
- ogg-01027(长事务)
OGG-01027(长事务) 示例9-25: WARNING OGG-01027 Long Running Transaction: XID 82.4.242063, Items 0, Extra ...