`

用Java线程协作模拟 - Alice,Bob和Robert博士的协作

阅读更多
1. 问题描述:

   Robert博士要进行一场实验,她需要两个助手Alice和Bob,Alice负责从一箱试管剂中取出优先级最高的试管剂(每个试管剂
都有编号ID,规定ID最小的优先级最高)放到试管剂台容器里,该容器里只能放入一个试管剂;当Alice把试管剂放到容器里后,
就会通知Bob,然后Bob把试管剂送到Rober博士的实验室,然后Robert又会通知Alice, Alice看到容器里空了,就会放入下一个
优先级最高的试管剂并通知Bob...如此循环。

  请用计算机模拟仿真该场景过程。

2. 问题分析:

   这是典型的对象通信问题。即线程间的协作问题。

3. 实现方法

(1) 一箱试管剂中取出优先级最高的试管剂(每个试管剂都有编号ID,规定ID最小的优先级最高)

     用优先级队列来模拟试管剂箱。

package boke.thread4;

/**
 * 基于数组的优先级队列【最小的元素具有最大优先权】
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.25
 * 
 */
public class PriorityQueue {
	public static void main(String[] args) throws PriorityQueueException {
		PriorityQueue pq = new PriorityQueue();
		pq.enQueue(10);
		pq.enQueue(40);
		pq.enQueue(43);
		pq.enQueue(20);
		pq.enQueue(50);
		pq.enQueue(30);
		pq.enQueue(99);

		while (!pq.isEmpty()) {
			int element = pq.delQueue();
			System.out.print(element + " ");
		}
		System.out.println("");
	}

	private int[] pqElements;
	private int count;
	private static final int MAX_PQ_SIZE = 1000;

	public PriorityQueue() {
		pqElements = new int[MAX_PQ_SIZE];
	}

	public void enQueue(int item) throws PriorityQueueException {
		if (!isFull()) {
			pqElements[count] = item;
			count++;
		} else {
			throw new PriorityQueueException("PriorityQueue is full!");
		}
	}

	public int delQueue() throws PriorityQueueException {
		if (!isEmpty()) {
			int min = pqElements[0];
			int minIndex = 0;

			for (int i = 1; i < count; i++) {
				if (pqElements[i] < min) {
					min = pqElements[i];
					minIndex = i;
				}
			}

			pqElements[minIndex] = pqElements[count - 1];
			count--;
			return min;
		} else {
			throw new PriorityQueueException("PriorityQueue is empty!");
		}
	}

	public void makeEmpty() {
		count = 0;
	}

	public boolean isEmpty() {
		return count == 0;
	}

	public boolean isFull() {
		return count == MAX_PQ_SIZE;
	}

	public int length() {
		return count;
	}
}

---------------------------------------

package boke.thread4;

/**
 * TODO 队列异常
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.25
 * 
 */
public class PriorityQueueException extends Exception {
	public PriorityQueueException() {
		super("Queue Exception");
	}

	public PriorityQueueException(String msg) {
		super(msg);
	}
}
(2) 试管剂台容器,该容器里只能放入一个试管剂。

package boke.thread4;

/**
 * 试管剂容器
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.25
 * 
 */
public class Container {
	int tubeID; // 试管剂ID
	boolean isFull = false; // 容器里是否有试管剂

	/**
	 * 容器里放入试管剂
	 * 
	 * @param ID
	 */
	public synchronized void put(int ID) {
		if (!isFull) { // 容器里没有试管剂
			tubeID = ID; // 放入试管剂
			System.out.println("Alice 把试管剂:" + tubeID + " 放入到容器里");
			isFull = true; // 则容器里有试管剂
			notify(); // 通知
		}
		try {
			wait(); // 自己等待
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 从容器里取走试管剂
	 * 
	 * @return
	 */
	public synchronized int get() {
		if (!isFull) { // 容器里没有试管剂
			try {
				wait(); // 等待
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		isFull = false; // 容器里有试管剂

		executeLogic(tubeID); // 执行业务逻辑

		notify();// 通知
		return tubeID; // 返回值
	}

	private void executeLogic(int value) {
		System.out.println("Bob 从容器里取走试管剂:" + value);
	}
}

(3) Alice

package boke.thread4;

/**
 * 模拟Alice
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.25
 * 
 */
class Alice extends Thread {
	Container c; // 容器
	PriorityQueue pq; // 优先级队列

	/**
	 * 构造方法
	 * 
	 * @param c
	 * @param pq
	 */
	Alice(Container c, PriorityQueue pq) {
		this.c = c;
		this.pq = pq;
	}

	/**
	 * 运行任务
	 */
	public void run() {
		try {
			while (!pq.isEmpty()) {
				int ID = pq.delQueue(); // 拿出优先级最高的试管剂
				c.put(ID); // 放置到容器里
			}
		} catch (PriorityQueueException e) {
			e.printStackTrace();
		}
	}
}

(4) Bob

package boke.thread4;

/**
 * 模拟Bob
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.25
 * 
 */
class Bob extends Thread {
	Container c; // 容器
	PriorityQueue pq; // 优先级队列

	/**
	 * 构造方法
	 * 
	 * @param c
	 * @param pq
	 */
	Bob(Container c, PriorityQueue pq) {
		this.c = c;
		this.pq = pq;
	}

	/**
	 * 运行任务
	 */
	public void run() {
		while (true) {
			c.get(); // Bob从容器里取出试管剂
		}
	}
}
(5) 场景类Client

package boke.thread4;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 场景类
 * 
 * @since jdk1.6
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.25
 * 
 */
public class Client {
	/**
	 * 
	 * @param args
	 * @throws PriorityQueueException
	 */
	public static void main(String[] args) throws PriorityQueueException {
		Container c = new Container(); // 容器
		PriorityQueue pq = new PriorityQueue(); // 优先级队列
		for (int i = 19; i < 100; i++) { // 试管剂
			pq.enQueue(i);
		}

		Alice alice = new Alice(c, pq); // Alice
		Bob bob = new Bob(c, pq); // Bob

		ExecutorService exec = Executors.newCachedThreadPool();
		exec.execute(alice);
		exec.execute(bob);
		exec.shutdown();
	}
}

4. 输出结果:

Alice 把试管剂:19 放入到容器里
Bob 从容器里取走试管剂:19
Alice 把试管剂:20 放入到容器里
Bob 从容器里取走试管剂:20
Alice 把试管剂:21 放入到容器里
Bob 从容器里取走试管剂:21
Alice 把试管剂:22 放入到容器里
Bob 从容器里取走试管剂:22
Alice 把试管剂:23 放入到容器里
Bob 从容器里取走试管剂:23
Alice 把试管剂:24 放入到容器里
Bob 从容器里取走试管剂:24
Alice 把试管剂:25 放入到容器里
Bob 从容器里取走试管剂:25
Alice 把试管剂:26 放入到容器里
Bob 从容器里取走试管剂:26
Alice 把试管剂:27 放入到容器里
Bob 从容器里取走试管剂:27
Alice 把试管剂:28 放入到容器里
Bob 从容器里取走试管剂:28
Alice 把试管剂:29 放入到容器里
Bob 从容器里取走试管剂:29
Alice 把试管剂:30 放入到容器里
Bob 从容器里取走试管剂:30
Alice 把试管剂:31 放入到容器里
Bob 从容器里取走试管剂:31
Alice 把试管剂:32 放入到容器里
Bob 从容器里取走试管剂:32
Alice 把试管剂:33 放入到容器里
Bob 从容器里取走试管剂:33
Alice 把试管剂:34 放入到容器里
Bob 从容器里取走试管剂:34
Alice 把试管剂:35 放入到容器里
Bob 从容器里取走试管剂:35
Alice 把试管剂:36 放入到容器里
Bob 从容器里取走试管剂:36
Alice 把试管剂:37 放入到容器里
Bob 从容器里取走试管剂:37
Alice 把试管剂:38 放入到容器里
Bob 从容器里取走试管剂:38
Alice 把试管剂:39 放入到容器里
Bob 从容器里取走试管剂:39
Alice 把试管剂:40 放入到容器里
Bob 从容器里取走试管剂:40
Alice 把试管剂:41 放入到容器里
Bob 从容器里取走试管剂:41
Alice 把试管剂:42 放入到容器里
Bob 从容器里取走试管剂:42
Alice 把试管剂:43 放入到容器里
Bob 从容器里取走试管剂:43
Alice 把试管剂:44 放入到容器里
Bob 从容器里取走试管剂:44
Alice 把试管剂:45 放入到容器里
Bob 从容器里取走试管剂:45
Alice 把试管剂:46 放入到容器里
Bob 从容器里取走试管剂:46
Alice 把试管剂:47 放入到容器里
Bob 从容器里取走试管剂:47
Alice 把试管剂:48 放入到容器里
Bob 从容器里取走试管剂:48
Alice 把试管剂:49 放入到容器里
Bob 从容器里取走试管剂:49
Alice 把试管剂:50 放入到容器里
Bob 从容器里取走试管剂:50
Alice 把试管剂:51 放入到容器里
Bob 从容器里取走试管剂:51
Alice 把试管剂:52 放入到容器里
Bob 从容器里取走试管剂:52
Alice 把试管剂:53 放入到容器里
Bob 从容器里取走试管剂:53
Alice 把试管剂:54 放入到容器里
Bob 从容器里取走试管剂:54
Alice 把试管剂:55 放入到容器里
Bob 从容器里取走试管剂:55
Alice 把试管剂:56 放入到容器里
Bob 从容器里取走试管剂:56
Alice 把试管剂:57 放入到容器里
Bob 从容器里取走试管剂:57
Alice 把试管剂:58 放入到容器里
Bob 从容器里取走试管剂:58
Alice 把试管剂:59 放入到容器里
Bob 从容器里取走试管剂:59
Alice 把试管剂:60 放入到容器里
Bob 从容器里取走试管剂:60
Alice 把试管剂:61 放入到容器里
Bob 从容器里取走试管剂:61
Alice 把试管剂:62 放入到容器里
Bob 从容器里取走试管剂:62
Alice 把试管剂:63 放入到容器里
Bob 从容器里取走试管剂:63
Alice 把试管剂:64 放入到容器里
Bob 从容器里取走试管剂:64
Alice 把试管剂:65 放入到容器里
Bob 从容器里取走试管剂:65
Alice 把试管剂:66 放入到容器里
Bob 从容器里取走试管剂:66
Alice 把试管剂:67 放入到容器里
Bob 从容器里取走试管剂:67
Alice 把试管剂:68 放入到容器里
Bob 从容器里取走试管剂:68
Alice 把试管剂:69 放入到容器里
Bob 从容器里取走试管剂:69
Alice 把试管剂:70 放入到容器里
Bob 从容器里取走试管剂:70
Alice 把试管剂:71 放入到容器里
Bob 从容器里取走试管剂:71
Alice 把试管剂:72 放入到容器里
Bob 从容器里取走试管剂:72
Alice 把试管剂:73 放入到容器里
Bob 从容器里取走试管剂:73
Alice 把试管剂:74 放入到容器里
Bob 从容器里取走试管剂:74
Alice 把试管剂:75 放入到容器里
Bob 从容器里取走试管剂:75
Alice 把试管剂:76 放入到容器里
Bob 从容器里取走试管剂:76
Alice 把试管剂:77 放入到容器里
Bob 从容器里取走试管剂:77
Alice 把试管剂:78 放入到容器里
Bob 从容器里取走试管剂:78
Alice 把试管剂:79 放入到容器里
Bob 从容器里取走试管剂:79
Alice 把试管剂:80 放入到容器里
Bob 从容器里取走试管剂:80
Alice 把试管剂:81 放入到容器里
Bob 从容器里取走试管剂:81
Alice 把试管剂:82 放入到容器里
Bob 从容器里取走试管剂:82
Alice 把试管剂:83 放入到容器里
Bob 从容器里取走试管剂:83
Alice 把试管剂:84 放入到容器里
Bob 从容器里取走试管剂:84
Alice 把试管剂:85 放入到容器里
Bob 从容器里取走试管剂:85
Alice 把试管剂:86 放入到容器里
Bob 从容器里取走试管剂:86
Alice 把试管剂:87 放入到容器里
Bob 从容器里取走试管剂:87
Alice 把试管剂:88 放入到容器里
Bob 从容器里取走试管剂:88
Alice 把试管剂:89 放入到容器里
Bob 从容器里取走试管剂:89
Alice 把试管剂:90 放入到容器里
Bob 从容器里取走试管剂:90
Alice 把试管剂:91 放入到容器里
Bob 从容器里取走试管剂:91
Alice 把试管剂:92 放入到容器里
Bob 从容器里取走试管剂:92
Alice 把试管剂:93 放入到容器里
Bob 从容器里取走试管剂:93
Alice 把试管剂:94 放入到容器里
Bob 从容器里取走试管剂:94
Alice 把试管剂:95 放入到容器里
Bob 从容器里取走试管剂:95
Alice 把试管剂:96 放入到容器里
Bob 从容器里取走试管剂:96
Alice 把试管剂:97 放入到容器里
Bob 从容器里取走试管剂:97
Alice 把试管剂:98 放入到容器里
Bob 从容器里取走试管剂:98
Alice 把试管剂:99 放入到容器里
Bob 从容器里取走试管剂:99

分享到:
评论
11 楼 wfine 2010-06-02  
建议PriorityQueue 用JDK自带PriorityBlockingQueue
10 楼 mathgl 2010-06-01  
producer-consumer model???

9 楼 select*from爱 2010-06-01  
maozj 写道
声明: 本人在javaeye网站上发布的论坛帖子都是原创,有些题目也是原创。。。如果评为新手帖 那说明实力不够 还需自我修养。。。但如果你只是看都没看就评为新手帖,那我只能说 你与技术无缘

+1
8 楼 littleJava 2010-06-01  
应该属于 生产者和消费者模式
7 楼 imhades 2010-06-01  
message queue...
6 楼 maozj 2010-06-01  
amwiacel 写道
对学习线程非常有用.....

呵呵 学习和分享。。。
5 楼 maozj 2010-06-01  
jy1245626 写道
楼主的帖子我觉得挺好,虽然不入高人耳目,但对我来说很有用,工作了四年多了多线程的接触几乎为0。

建议je对评分进行改进

评任何一个级别的帖子都必须回帖说出理由,否则不予评贴


谢谢支持~~ 只要每个人有心 都可以把自己好的想法发布出来 分享才快乐~~
4 楼 amwiacel 2010-06-01  
对学习线程非常有用.....
3 楼 jy1245626 2010-06-01  
楼主的帖子我觉得挺好,虽然不入高人耳目,但对我来说很有用,工作了四年多了多线程的接触几乎为0。

建议je对评分进行改进

评任何一个级别的帖子都必须回帖说出理由,否则不予评贴
2 楼 maozj 2010-06-01  
声明: 本人在javaeye网站上发布的论坛帖子都是原创,有些题目也是原创。。。如果评为新手帖 那说明实力不够 还需自我修养。。。但如果你只是看都没看就评为新手帖,那我只能说 你与技术无缘
1 楼 maozj 2010-06-01  
新手帖? 谁评的 题目都是原创

相关推荐

Global site tag (gtag.js) - Google Analytics