import Utilities.*; class QueueItem { private String value = ""; private QueueItem nextItem = null; public QueueItem() {} public QueueItem(String value) { this.value = value; } public QueueItem(String value, QueueItem nextItem) { this.value = value; this.nextItem = nextItem; } public String toString() { return value; } public String valueGet() { return value; } public void valueSet(String value) { this.value = value; } public QueueItem nextItemGet() { return nextItem; } public void nextItemSet(QueueItem nextItem) { this.nextItem = nextItem; } } class QueueException extends Exception {} class EmptyQueueException extends QueueException {} class CorruptedQueueException extends QueueException {} class Queue extends MyObject { private QueueItem head = null, tail = null; private int count = 0; public Queue() { System.out.println("Queue is alive"); } public String toString() { String result = ""; QueueItem one = head; while (one != null) { result += " " + one; one = one.nextItemGet(); } return result; } public void enQueue(String value, boolean doContextSwitch) throws CorruptedQueueException { QueueItem oldTail = null; QueueItem newOne = new QueueItem(value); if (tail == null) { // add to an empty queue if (head != null) throw new CorruptedQueueException(); else { head = newOne; tail = newOne; } } else { // add to end of queue oldTail = tail; if (doContextSwitch) nap(1500); tail = newOne; oldTail.nextItemSet(newOne); } count++; System.out.println("enQueue: there are now " + count + " nodes in the queue"); } public String deQueue() throws EmptyQueueException, CorruptedQueueException { QueueItem oldOne = null; if (head == null && tail == null) throw new EmptyQueueException(); else if (head != null && tail != null) { if (head == tail) { // dequeue from a singleton queue oldOne = head; head = null; tail = null; } else { // dequeue from beginning of queue oldOne = head; head = oldOne.nextItemGet(); } count--; System.out.println("deQueue: there are now " + count + " nodes in the queue"); } else throw new CorruptedQueueException(); return oldOne.valueGet(); } } class Aenq extends MyObject implements Runnable { private Queue q = null; public Aenq(Queue q) { this.q = q; } public void run() { try { for (int i = 1; i <= 4; i++) { q.enQueue("item"+i, false); System.out.println("age()=" + age() + ", Aenq: q=\n" + q); nap(1000); } } catch (CorruptedQueueException e) { System.out.println(e); } } } class Benq extends MyObject implements Runnable { private Queue q = null; private boolean doContextSwitch = false; public Benq(Queue q, boolean doContextSwitch) { this.q = q; this.doContextSwitch = doContextSwitch; } public void run() { nap(1000); try { for (int i = 5; i <= 9; i++) { q.enQueue("item"+i, doContextSwitch && i==6); System.out.println("age()=" + age() + ", Benq: q=\n" + q); nap(1000); } } catch (CorruptedQueueException e) { System.out.println(e); } } } class QueueRace extends MyObject { private static void deQueueItemAndPrint(Queue q) { try { System.out.println("age()=" + age() + ", QueueRace: dequeue " + q.deQueue()); } catch (QueueException e) { System.out.println(e); } } public static void main(String[] args) { Queue q = new Queue(); boolean doContextSwitch = false; try { doContextSwitch = Boolean.valueOf(args[0]).booleanValue(); } catch (ArrayIndexOutOfBoundsException e) {} System.out.println("QueueRace alive, doContextSwitch=" + doContextSwitch); new Thread(new Aenq(q)).start(); new Thread(new Benq(q, doContextSwitch)).start(); nap(2000); for (int i = 1; i <= 10; i++) { deQueueItemAndPrint(q); nap(1000*((i % 4) + 1)); } } } /* ............... Example compile and run(s) D:\>javac qrac.java D:\>java QueueRace Queue is alive QueueRace alive, doContextSwitch=false enQueue: there are now 1 nodes in the queue age()=110, Aenq: q= item1 enQueue: there are now 2 nodes in the queue age()=1150, Aenq: q= item1 item2 enQueue: there are now 3 nodes in the queue age()=1150, Benq: q= item1 item2 item5 deQueue: there are now 2 nodes in the queue age()=2090, QueueRace: dequeue item1 enQueue: there are now 3 nodes in the queue age()=2140, Aenq: q= item2 item5 item3 enQueue: there are now 4 nodes in the queue age()=2140, Benq: q= item2 item5 item3 item6 enQueue: there are now 5 nodes in the queue age()=3130, Aenq: q= item2 item5 item3 item6 item4 enQueue: there are now 6 nodes in the queue age()=3130, Benq: q= item2 item5 item3 item6 item4 item7 deQueue: there are now 5 nodes in the queue age()=4120, QueueRace: dequeue item2 enQueue: there are now 6 nodes in the queue age()=4170, Benq: q= item5 item3 item6 item4 item7 item8 enQueue: there are now 7 nodes in the queue age()=5160, Benq: q= item5 item3 item6 item4 item7 item8 item9 deQueue: there are now 6 nodes in the queue age()=7080, QueueRace: dequeue item5 deQueue: there are now 5 nodes in the queue age()=11090, QueueRace: dequeue item3 deQueue: there are now 4 nodes in the queue age()=12140, QueueRace: dequeue item6 deQueue: there are now 3 nodes in the queue age()=14110, QueueRace: dequeue item4 deQueue: there are now 2 nodes in the queue age()=17130, QueueRace: dequeue item7 deQueue: there are now 1 nodes in the queue age()=21140, QueueRace: dequeue item8 deQueue: there are now 0 nodes in the queue age()=22130, QueueRace: dequeue item9 EmptyQueueException D:\>java QueueRace true Queue is alive QueueRace alive, doContextSwitch=true enQueue: there are now 1 nodes in the queue age()=50, Aenq: q= item1 enQueue: there are now 2 nodes in the queue age()=1100, Aenq: q= item1 item2 enQueue: there are now 3 nodes in the queue age()=1100, Benq: q= item1 item2 item5 deQueue: there are now 2 nodes in the queue age()=2030, QueueRace: dequeue item1 enQueue: there are now 3 nodes in the queue age()=2090, Aenq: q= item2 item5 item3 enQueue: there are now 4 nodes in the queue age()=3080, Aenq: q= item2 item5 item3 item4 enQueue: there are now 5 nodes in the queue age()=3570, Benq: q= item2 item5 item3 item6 deQueue: there are now 4 nodes in the queue age()=4060, QueueRace: dequeue item2 enQueue: there are now 5 nodes in the queue age()=4610, Benq: q= item5 item3 item6 item7 enQueue: there are now 6 nodes in the queue age()=5600, Benq: q= item5 item3 item6 item7 item8 enQueue: there are now 7 nodes in the queue age()=6590, Benq: q= item5 item3 item6 item7 item8 item9 deQueue: there are now 6 nodes in the queue age()=7080, QueueRace: dequeue item5 deQueue: there are now 5 nodes in the queue age()=11090, QueueRace: dequeue item3 deQueue: there are now 4 nodes in the queue age()=12080, QueueRace: dequeue item6 deQueue: there are now 3 nodes in the queue age()=14060, QueueRace: dequeue item7 deQueue: there are now 2 nodes in the queue age()=17080, QueueRace: dequeue item8 deQueue: there are now 1 nodes in the queue age()=21090, QueueRace: dequeue item9 EmptyQueueException EmptyQueueException ... end of example run(s) */