Guarded Suspension模式 --等我准备好

定义:

Suspension模式通过线程等待来保证实例的安全性。

引例

类的一览表
名字说明
Request请求类
RequestQueue依次存放求情的类
ClientThread发送请求类
ServerThread接受请求类
Main测试行为类
public class Request {
	private final String name;

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

	public String getName() {
		return name;
	}

	public String toString() {
		return "[ Request " + name + " ]";
	}
}
public class RequestQueue {
	// 有点像消息队列。生产者与消费者
	private final LinkedList queue = new LinkedList();

	public synchronized Request getRequest() {
		while (queue.size() <= 0) {
			try {
				// 队列为空则等待阻塞
				wait();
			} catch (InterruptedException e) {
			}
		}
		return (Request) queue.removeFirst();
	}

	public synchronized void putRequest(Request request) {
		queue.addLast(request);
		notifyAll();
	}
}
public class ClientThread extends Thread {
	private Random random;
	private RequestQueue requestQueue;

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

	public void run() {
		for (int i = 0; i < 10000; i++) {
			Request request = new Request("No." + i);
			System.out.println(Thread.currentThread().getName() + " requests " + request);
			requestQueue.putRequest(request);
			try {
				Thread.sleep(random.nextInt(1000));
			} catch (InterruptedException e) {
			}
		}
	}
}
public class ServerThread extends Thread {
	private Random random;
	private RequestQueue requestQueue;

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

	public void run() {
		for (int i = 0; i < 10000; i++) {
			Request request = requestQueue.getRequest();
			System.out.println(Thread.currentThread().getName() + " handles  " + request);
			try {
				Thread.sleep(random.nextInt(1000));
			} catch (InterruptedException e) {
			}
		}
	}
}
public class Main {
	public static void main(String[] args) {
		RequestQueue requestQueue = new RequestQueue();
		new ClientThread(requestQueue, "Alice", 3141592L).start();
		new ServerThread(requestQueue, "Bobby", 6535897L).start();
	}
}

结果: 

Alice requests [ Request No.0 ]
Bobby handles  [ Request No.0 ]
Alice requests [ Request No.1 ]
Alice requests [ Request No.2 ]
Bobby handles  [ Request No.1 ]
Bobby handles  [ Request No.2 ]
Alice requests [ Request No.3 ]
Bobby handles  [ Request No.3 ]
Alice requests [ Request No.4 ]
Bobby handles  [ Request No.4 ]
Alice requests [ Request No.5 ]
Alice requests [ Request No.6 ]

 Suspension模式 中的角色

GuardedObject(被守护的对象)是一个持有被守护方法的类。当线程执行守护方法时,若守护条件成立则执行,若不成立则等待。守护条件的成立会随着被守护的对象状态发生改变。

问题思考:

死锁的问题,A与B通过发送请求对话。

public class Request {
    private final String name;
    public Request(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String toString() {
        return "[ Request " + name + " ]";
    }
}
public class RequestQueue {
    private final LinkedList queue = new LinkedList();
    public synchronized Request getRequest() {
        while (queue.size() <= 0) {
            try {                                   
                wait();
            } catch (InterruptedException e) {      
            }                                       
        }                                           
        return (Request)queue.removeFirst();
    }
    public synchronized void putRequest(Request request) {
        queue.addLast(request);
        notifyAll();
    }
}
public class TalkThread extends Thread {
    private RequestQueue input;
    private RequestQueue output;
    public TalkThread(RequestQueue input, RequestQueue output, String name) {
        super(name);
        this.input = input;
        this.output = output;
    }
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":BEGIN");
        for (int i = 0; i < 20; i++) {
            // 取得对方的请求
            Request request1 = input.getRequest();
            System.out.println(Thread.currentThread().getName() + " gets  " + request1);

            //加上一个感叹号(!)传给对方
            Request request2 = new Request(request1.getName() + "!");
            System.out.println(Thread.currentThread().getName() + " puts  " + request2);
            output.putRequest(request2);
        }
        System.out.println(Thread.currentThread().getName() + ":END");
    }
}
public class Main {
	public static void main(String[] args) {
		RequestQueue requestQueue1 = new RequestQueue();
		RequestQueue requestQueue2 = new RequestQueue();
		// 种下一个种子,防止发生死锁
		// requestQueue1.putRequest(new Request("Hello"));
		new TalkThread(requestQueue1, requestQueue2, "Alice").start();
		new TalkThread(requestQueue2, requestQueue1, "Bobby").start();
	}
}

结果

Bobby:BEGIN
Alice:BEGIN

如何解决呢? 放开注释,事先种下一个请求。这样就不会出现相互等待对方发起第一次会话。

我们继续向下看!这样写有什么意思呢??

public class Channel {
	private RequestQueue input;
	private RequestQueue output;

	public Channel(RequestQueue input, RequestQueue output) {
		this.input = input;
		this.output = output;
	}

	public RequestQueue getInput() {
		return input;
	}

	public RequestQueue getOutput() {
		return output;
	}

}
public class TalkThread extends Thread {
	private Channel channel;

	public TalkThread(Channel channel, String name) {
		super(name);
		synchronized (channel) {
			this.channel = channel;
		}
	}

	public void run() {
		System.out.println(Thread.currentThread().getName() + ":BEGIN");
		for (int i = 0; i < 20; i++) {
			// 取得对方的请求
			Request request1 = channel.getInput().getRequest();
			System.out.println(Thread.currentThread().getName() + " gets  " + request1);

			// 加上一个感叹号(!)传给对方
			Request request2 = new Request(request1.getName() + "!");
			System.out.println(Thread.currentThread().getName() + " puts  " + request2);
			channel.getOutput().putRequest(request2);
		}
		System.out.println(Thread.currentThread().getName() + ":END");
	}
}
public class Main {
	public static void main(String[] args) {
		RequestQueue requestQueue1 = new RequestQueue();
		RequestQueue requestQueue2 = new RequestQueue();
		Channel channel = new Channel(requestQueue1, requestQueue1);
		// 种下一个种子,防止发生死锁
		requestQueue1.putRequest(new Request("Hello"));
		new TalkThread(channel, "Alice").start();
		new TalkThread(channel, "Bobby").start();
	}
}

 有点像netty通信管道的意思!!自己体会一下

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值