java多线程之Worker Thread模式

Worker Thread模式(工作没来,就一直等,工作来了就干活)

Worker的意思是工作的人,在worker Thread 模式中,工人线程(worker thread)会逐个取回工作并进行处理,当所有的工作全部完成后,工人线程会等待新的工作来。

 

下面来看看程序实例图:

 

ClientTread 表示发出工作请求的线程的类

Request 表示工作请求的类

Channel 接收工作请求并将工作请求交给工人线程的类

WorkerThread 表示工人线程的类

 

Request类:

name表示发出委托请求的名字

number表示发出请求的编号

execute就是模拟执行请求的动作

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()+" excutes "+this);

try {

Thread.sleep(random.nextInt(1000));

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public String toString(){

return "[Request from "+name+" No."+ number +" ]";

}

}

ClientThread类

创建request的实例,并将实例传给Channel类的putRequest的方法

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;

}

public void run(){

try {

for(int i = 0;true;i++){

Request request = new Request(getName(), i);

channel.putRequest(request);

Thread.sleep(1000);

}

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

Channel类

requestQueue是用于保存请求的队列的角色

treadPool是WorkerThread的数组

putRequest方法用于将请求加入到队列中

takeRequest方法用于取出队列的请求

takeRequest,putRequest必须等到满足条件才能执行,不然就一直等待(Guarded Suspension)模式

startWorkers是启动所有工人线程的方法

public class Channel {

private static final int MAX_REQUEST = 100;

private final Request[] requestQueue;

private int tail;//下次putRequest的位置

private int head;//下次takeRequest的位置

private int count;//Request的数量

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();

}

}

public synchronized void putRequest(Request request){

while(count >= requestQueue.length){

try {

wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

requestQueue[tail] = request;

tail = (tail+1)%requestQueue.length;

count++;

notifyAll();

}

public synchronized Request takeRequest(){

while(count <=0){

try {

wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

Request request = requestQueue[head];

head = (head+1)% requestQueue.length;

count--;

notifyAll();

return request;

}

}

WorkerThread类

调用takeRequest方法从Channel类获取一个Request实例,然后再执行Request操作(而且是反复执行这样的操作)

public class WorkerThread extends Thread{

private final Channel channel;

public WorkerThread(String name,Channel channel){

this.channel = channel;

}

public void run(){

while(true){

Request request = channel.takeRequest();

request.execute();

}

}

}

5.Main类:

创建一个雇佣5个工人的实例,并为他们分配处理三个任务

public class Main {

public static void main(String[] args) {

Channel channel = new Channel(5);

channel.startWorkers();

new ClientThread("Alice", channel).start();

new ClientThread("Bob", channel).start();

new ClientThread("Cici", channel).start();

}

}

结果:

Thread-3 excutes [Request from Alice No.0 ]

Thread-2 excutes [Request from Cici No.0 ]

Thread-4 excutes [Request from Bob No.0 ]

Thread-4 excutes [Request from Alice No.1 ]

Thread-3 excutes [Request from Bob No.1 ]

Thread-1 excutes [Request from Cici No.1 ]

 

扩展使用Executors创建线程池(升级简化)

Main类

使用Executors.newFixedThreadPool()方法创建线程池保存着指定的数量的线程的是一个ExecutorService对象

public class Main {

public static void main(String[] args) {

ExecutorService executorService  = Executors.newFixedThreadPool(5);

try {

new ClientThread("Alice", executorService).start();

new ClientThread("Bob", executorService).start();

new ClientThread("Cici", executorService).start();

Thread.sleep(5000);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally{

executorService.shutdown();

}

}

}

ClientThread类通过Executor.ExecutorService接口使用线程池,当ExecuteService进入终止处理后,execute方法会被拒绝执行,并抛出RejectedExecutionException异常

 

public class ClientThread extends Thread{

//private final Channel channel;

private final ExecutorService executorService;

private static final Random random = new Random();

public ClientThread(String name,ExecutorService executorService){

super(name);

this.executorService = executorService;

}

public void run(){

try {

for(int i = 0;true;i++){

Request request = new Request(getName(), i);

//channel.putRequest(request);

executorService.execute(request);

Thread.sleep(1000);

}

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

3.Request类

为了能够让ExecutorService使用Request类,实现了Runnable接口,并在run方法中编写实际的处理

public class Request implements Runnable{

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 String toString(){

return "[Request from "+name+" No."+ number +" ]";

}

@Override

public void run() {

// TODO Auto-generated method stub

System.out.println(Thread.currentThread().getName()+" excutes "+this);

try {

Thread.sleep(random.nextInt(1000));

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

执行结果:

pool-1-thread-3 excutes [Request from Bob No.0 ]

pool-1-thread-2 excutes [Request from Alice No.0 ]

pool-1-thread-1 excutes [Request from Cici No.0 ]

pool-1-thread-4 excutes [Request from Bob No.1 ]

pool-1-thread-1 excutes [Request from Cici No.1 ]

pool-1-thread-5 excutes [Request from Alice No.1 ]

pool-1-thread-3 excutes [Request from Bob No.2 ]

pool-1-thread-2 excutes [Request from Cici No.2 ]

pool-1-thread-1 excutes [Request from Alice No.2 ]

pool-1-thread-5 excutes [Request from Bob No.3 ]

pool-1-thread-4 excutes [Request from Cici No.3 ]

pool-1-thread-3 excutes [Request from Alice No.3 ]

pool-1-thread-1 excutes [Request from Bob No.4 ]

pool-1-thread-2 excutes [Request from Alice No.4 ]

pool-1-thread-3 excutes [Request from Cici No.4 ]

Exception in thread "Bob" java.util.concurrent.RejectedExecutionException: Task [Request from Bob No.5 ] rejected from

总结:

如果每次发送工作请求时都要执行工作的新线程就太浪费了,我们可以事先启动执行工作的线程(工人线程),然后使用Producer-Consumer模式将表示工作内容的实例传递给工作线程,这样修改后,工人线程就会帮我们进行工作,而不用再启动新的线程。这就是Worker Thread模式。

猜你喜欢

转载自blog.csdn.net/qq_31350373/article/details/80455207