1. 程式人生 > >java多執行緒系列之模式|第一篇-Guarded Suspension pattern

java多執行緒系列之模式|第一篇-Guarded Suspension pattern

Guarded Suspension pattern模式

作者注:該系列文章基於《java執行緒設計模式》撰寫,只用於學習和交流。 定義:多執行緒執行,當前執行緒沒有達到警戒條件時,執行緒會進入等待直到被喚醒,該模式被稱為Guarded Suspension pattern模式。 其順序圖如下: Guarded Suspension pattern 順序圖

程式碼示例 Request 類,請求封裝的實體類,這是設計模式中很常見的方式,這樣有利於承載及儲存。

package pattern.guard.suspension;

public class Request {

    private final String name;

    public Request(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Request{" +
                "name='" + name + '\'' +
                '}';
    }
}

RequestQueue,請求物件的承載類,內部實現使用了連結串列。

package pattern.guard.suspension;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;

public class RequestQueue {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private final LinkedList<Request> queue=new LinkedList<Request>();

    public synchronized Request getQueue(){
        while(queue.size()<=0){
            try{
                wait();
            }catch (InterruptedException e){
                log.error(e.getMessage());
            }

        }
        return queue.removeFirst();
    }

    public synchronized void putRequest(Request request){
        queue.addLast(request);
        notifyAll();
    }



}

ClientThread,用於生成請求物件的執行緒類。

package pattern.guard.suspension;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;

public class ClientThread extends Thread {

    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private Random random;
    private RequestQueue requestQueue;

    public ClientThread(RequestQueue requestQueue,String name,long seed){
        super(name);
        this.requestQueue=requestQueue;
        this.random=new Random(seed);
    }

    @Override
    public void run(){
        for (int i = 0; i < 10000; i++) {
            Request request=new Request("No."+i);
            System.out.println(Thread.currentThread().getName()+" request"+request);
            requestQueue.putRequest(request);
            try{
                Thread.sleep(random.nextInt(1000));
            }catch(Exception e){
                log.error(e.getMessage());
            }
        }

    }



}

ServerThread,請求服務類,處理業務邏輯的地方。

package pattern.guard.suspension;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;

public class ServerThread extends Thread{

    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private Random random;
    private RequestQueue requestQueue;
    public ServerThread(RequestQueue requestQueue,String name,long seed){
        super(name);
        this.requestQueue=requestQueue;
        this.random=new Random(seed);
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            Request request= requestQueue.getQueue();
            System.out.println(Thread.currentThread().getName()+" request"+request);
            try{
                Thread.sleep(random.nextInt(1000));
            }catch(Exception e){
                log.error(e.getMessage());
            }
        }
    }
}

main測試類

package pattern.guard.suspension;

public class Main {


    public static void main(String[] args){
        RequestQueue queue=new RequestQueue();
        new ClientThread(queue,"Alice",3141592L).start();
        new ServerThread(queue,"Bobby",6525293L).start();
    }

}

程式碼解讀: putRequest:往佇列中存放一個請求,然後喚醒該物件所有的等待集。 getRequest:從佇列中取出第一條請求,其警戒條件為while(queue.size()<=0),當執行緒達到這個條件時會進入該物件等待集並釋放執行緒持有的物件鎖,這就是guarded suspension-防衛阻止的意思。

測試結果:

Alice requestRequest{name='No.0'}
Bobby requestRequest{name='No.0'}
Alice requestRequest{name='No.1'}
Bobby requestRequest{name='No.1'}
Alice requestRequest{name='No.2'}
Bobby requestRequest{name='No.2'}
Alice requestRequest{name='No.3'}
Bobby requestRequest{name='No.3'}
Alice requestRequest{name='No.4'}
Bobby requestRequest{name='No.4'}
。。。

SUCCESS.