001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package dso;
005:
006: import java.util.HashMap;
007: import java.util.LinkedList;
008: import java.util.List;
009: import java.util.Map;
010:
011: /**
012: * @author steve
013: */
014: public class SimpleSharedQueueExample {
015: private final static int MAX_RESULTS_SIZE = 15;
016: private String putterName;
017: private List workQueue = new LinkedList();
018: private Map allWorkers = new HashMap();
019: private List results = new LinkedList();
020: //ARI: Keep summary info as we add results so that we can print a pretty
021: // summary
022: private Map resultsSummary = new HashMap();
023:
024: public SimpleSharedQueueExample() {
025: synchronized (allWorkers) {
026: int myID = allWorkers.size() + 1;
027: this .putterName = "Worker:" + myID;
028: this .allWorkers.put(putterName, new Integer(myID));
029: }
030: Thread t = new WorkerThread(this , putterName);
031: t.setDaemon(true);
032: t.start();
033: }
034:
035: /**
036: * Add a calculation to the work queue to be picked up later by what ever node gets it first and executed.
037: *
038: * @param number1 - first item in the calculation
039: * @param number2 - second item in the calculation
040: * @param sign - calculation to perform
041: */
042: public void addAction(float number1, float number2, char sign,
043: int timesRepeat) {
044: for (int i = 0; i < timesRepeat; i++) {
045: put(new Action(putterName, number1, number2, sign));
046: }
047: }
048:
049: /**
050: * The name of this node.
051: *
052: * @return
053: */
054: public String getPutterName() {
055: return putterName;
056: }
057:
058: /**
059: * remove all the results from the results collection
060: */
061: public void clearResults() {
062: synchronized (results) {
063: results.clear();
064: }
065: }
066:
067: /**
068: * Get all the results so far from all nodes and return them
069: *
070: * @return List of results
071: */
072: public List getResults() {
073: synchronized (results) {
074: return new LinkedList(results);
075: }
076: }
077:
078: public HashMap getResultsSummary() {
079: synchronized (resultsSummary) {
080: return new HashMap(resultsSummary);
081: }
082: }
083:
084: private void addResultSummary(Result result) {
085: synchronized (resultsSummary) {
086: ResultsSummary rs = null;
087: if (!resultsSummary.containsKey(result.getPutterName())) {
088: resultsSummary
089: .put(result.getPutterName(),
090: new ResultsSummary(result
091: .getPutterName(), 0, 0));
092: }
093: rs = (ResultsSummary) resultsSummary.get(result
094: .getPutterName());
095: rs.incrementPutCount();
096:
097: if (!resultsSummary.containsKey(result.getExecuterName())) {
098: resultsSummary.put(result.getExecuterName(),
099: new ResultsSummary(result.getExecuterName(), 0,
100: 0));
101: }
102: rs = (ResultsSummary) resultsSummary.get(result
103: .getExecuterName());
104: rs.incrementExecuteCount();
105: }
106: }
107:
108: private void addResult(Result result) {
109: synchronized (results) {
110: results.add(result.toString());
111: if (results.size() > MAX_RESULTS_SIZE) {
112: results.remove(0);
113: }
114: }
115: addResultSummary(result);
116: }
117:
118: private void put(Action action) {
119: synchronized (workQueue) {
120: workQueue.add(action);
121: workQueue.notifyAll();
122: }
123: }
124:
125: private Result execute(String executerName) {
126: synchronized (workQueue) {
127: while (workQueue.size() == 0) {
128: try {
129: workQueue.wait();
130: } catch (InterruptedException e) {
131: throw new RuntimeException(e);
132: }
133: }
134: Action action = (Action) workQueue.remove(0);
135: String result = action.execute(executerName);
136: return new Result(action, executerName, result);
137: }
138: }
139:
140: public static class Action {
141: private float number1, number2;
142: private char sign;
143: private String putterName;
144:
145: public Action(String putter, float number1, float number2,
146: char sign) {
147: this .putterName = putter;
148: this .number1 = number1;
149: this .number2 = number2;
150: this .sign = sign;
151: }
152:
153: public String execute(String executerName) {
154: try {
155: switch (sign) {
156: case '+':
157: return "" + (number1 + number2);
158: case '-':
159: return "" + (number1 - number2);
160: case '*':
161: return "" + (number1 * number2);
162: case '/':
163: return "" + (number1 / number2);
164: default:
165: return "error:" + sign;
166: }
167: } catch (Exception e) {
168: return "Invalid calculation:" + number1 + "" + sign
169: + number2;
170: }
171: }
172:
173: public String toString() {
174: return "Sign:" + sign + " putter:" + putterName
175: + " number1:" + number1 + " number2:" + number2;
176: }
177:
178: public float getNumber1() {
179: return number1;
180: }
181:
182: public float getNumber2() {
183: return number2;
184: }
185:
186: public char getSign() {
187: return sign;
188: }
189:
190: public String getPutterName() {
191: return putterName;
192: }
193: }
194:
195: private static class ResultsSummary {
196: private String name;
197: private int putCount;
198: private int executeCount;
199:
200: public String toString() {
201: return "<tr>\n<td>" + this .name + "</td><td>"
202: + this .executeCount + "</td><td>" + this .putCount
203: + "</td></tr>";
204: }
205:
206: public ResultsSummary(String name, int p, int e) {
207: this .name = name;
208: this .putCount = p;
209: this .executeCount = e;
210: }
211:
212: public void incrementExecuteCount() {
213: this .executeCount++;
214: }
215:
216: public void incrementPutCount() {
217: this .putCount++;
218: }
219:
220: public String getName() {
221: return this .name;
222: }
223:
224: public int getExecuteCount() {
225: return this .executeCount;
226: }
227:
228: public int getPutCount() {
229: return this .putCount;
230: }
231: }
232:
233: private static class Result {
234: private String putterName;
235: private String executerName;
236: private float number1;
237: private float number2;
238: private char sign;
239: private String result;
240:
241: public String toString() {
242: return "Created by: " + putterName + " Executed by: "
243: + executerName + " equation ( " + number1 + " "
244: + sign + " " + number2 + " = " + result + " )";
245: }
246:
247: public Result(Action action, String executerName, String result) {
248: this .putterName = action.getPutterName();
249: this .executerName = executerName;
250: this .number1 = action.getNumber1();
251: this .number2 = action.getNumber2();
252: this .sign = action.getSign();
253: this .result = result;
254: }
255:
256: public String getPutterName() {
257: return this .putterName;
258: }
259:
260: public String getExecuterName() {
261: return this .executerName;
262: }
263: }
264:
265: private static class WorkerThread extends Thread {
266: private String putterName;
267: private SimpleSharedQueueExample parent;
268:
269: public WorkerThread(SimpleSharedQueueExample parent,
270: String putterName) {
271: this .parent = parent;
272: this .putterName = putterName;
273: }
274:
275: public void run() {
276: while (true) {
277: Result result = null;
278: result = parent.execute(putterName);
279: if (result != null) {
280: parent.addResult(result);
281: }
282: }
283: }
284: }
285: }
|