본문 바로가기

Development/Programming

[Java Design Patten] Worker Thread 패턴

Worker Thread 패턴에서는 Worker thread가 일을 하니씩 가지러 가고, 또 처리합니다. 일이 없으면 Worker thread는 새로운 일이 올때까지 대기합니다.


Client 역할

업무를 작성하여 Channel역할에게 일을 전 달


public class ClientThread extends  Thread {

private final Channel channel;

private static final Random random = new Random();

public ClientThread (final String name, final Channel channel) {

super(name);

this.channel = channel;

}


public void run () {

try {

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

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

channel.putRequest(request);

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

}

} catch (final InterruptedException e) {

}

}

}



Channel 역할

Client 역할로부터 Request 역할을 받아 Worker 역할에 건넵니다.


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 (final int threads) {

this.requestQueue = new Request[MAX_REQUEST];

this.tail = 0;

this.head = 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 (final Request request) {

while (count >= requestQueue.length) {

try {

wait();

} catch (final InterruptedException e) {

e.printStackTrace();

}

}

requestQueue[tail] = request;

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

count++;

notifyAll();

}

public synchronized Request takeRequest () {

while (count <= 0) {

try {

wait();

} catch (final InterruptedException e) {

e.printStackTrace();

}

}

Request request = requestQueue[head];

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

count--;

notifyAll();

return request;

}

}


Worker 역할

Channel 역할로부터 Request 역할을 받아 그 업무를 실행


public class WorkerThread extends Thread {

private final Channel channel;

public WorkerThread (final String name, final Channel channel) {

super (name);

this.channel = channel;

}

public void run () {

while (true) {

final Request request = this.channel.takeRequest();

request.execute();

}

}

}


Request 역할

업무를 표현하기 위한 역할


public class Request {

private final String name;

private final int number;

private static final Random random = new Random();

public Request (final String name, final 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 (final InterruptedException e) {

e.printStackTrace();

}

}

}



실행 예시


public class Main {

public static void main (final String [] args) {

final Channel channel = new Channel(5);

channel.startWorkers();

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

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

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

}

}