001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.util;
020:
021: import java.util.ArrayList;
022: import java.util.List;
023: import java.util.Random;
024:
025: import org.apache.batik.test.AbstractTest;
026: import org.apache.batik.test.TestReport;
027:
028: public class RunnableQueueTest extends AbstractTest {
029:
030: public int nThreads;
031: public int activeThreads;
032: public Random rand;
033: public RunnableQueue rq;
034:
035: /**
036: * Creates a new RunnableQueueTest.
037: * @param nThreads number of runnables to queue
038: */
039: public RunnableQueueTest(int nThreads) {
040: this .nThreads = nThreads;
041: }
042:
043: public RunnableQueueTest(Integer nThreads) {
044: this ((nThreads == null) ? 10 : nThreads.intValue());
045: }
046:
047: /**
048: * Returns this Test's name
049: */
050: public String getName() {
051: return "RunnableQueue Stress Test";
052: }
053:
054: /**
055: * This method will only throw exceptions if some aspect
056: * of the test's internal operation fails.
057: */
058: public TestReport runImpl() throws Exception {
059: rq = RunnableQueue.createRunnableQueue();
060:
061: List l = new ArrayList(nThreads);
062: rand = new Random(2345);
063:
064: // Two switch flickers to make things interesting...
065: l.add(new SwitchFlicker());
066: l.add(new SwitchFlicker());
067:
068: for (int i = 0; i < nThreads; i++) {
069: Runnable rqRable = new RQRable(i, rand.nextInt(50) + 1);
070: l.add(new TPRable(rq, i, rand.nextInt(4) + 1, rand
071: .nextInt(500) + 1, 20, rqRable));
072: }
073:
074: synchronized (this ) {
075: ThreadPounder tp = new ThreadPounder(l);
076: tp.start();
077: activeThreads = nThreads;
078: while (activeThreads != 0) {
079: wait();
080: }
081: }
082:
083: System.exit(0);
084: return null;
085: }
086:
087: public class SwitchFlicker implements Runnable {
088: public void run() {
089: boolean suspendp, waitp;
090: int time;
091: while (true) {
092: try {
093: synchronized (rand) {
094: suspendp = rand.nextBoolean();
095: waitp = rand.nextBoolean();
096: time = rand.nextInt(500);
097: }
098: if (suspendp) {
099: // 1/2 of the time suspend, 1/2 time wait, 1/2 the
100: // time don't
101: rq.suspendExecution(waitp);
102: System.out.println("Suspended - "
103: + (waitp ? "Wait" : "Later"));
104: Thread.sleep(time / 10);
105: } else {
106: // 1/2 the time resume
107: rq.resumeExecution();
108: System.out.println("Resumed");
109: Thread.sleep(time);
110: }
111: } catch (InterruptedException ie) {
112: }
113: }
114: }
115: }
116:
117: public static final int INVOKE_LATER = 1;
118: public static final int INVOKE_AND_WAIT = 2;
119: public static final int PREEMPT_LATER = 3;
120: public static final int PREEMPT_AND_WAIT = 4;
121:
122: public class TPRable implements Runnable {
123:
124: RunnableQueue rq;
125: int idx;
126: int style;
127: long repeatDelay;
128: int count;
129: Runnable rqRable;
130:
131: TPRable(RunnableQueue rq, int idx, int style, long repeatDelay,
132: int count, Runnable rqRable) {
133: this .rq = rq;
134: this .idx = idx;
135: this .style = style;
136: this .repeatDelay = repeatDelay;
137: this .count = count;
138: this .rqRable = rqRable;
139: }
140:
141: public void run() {
142: try {
143: while (count-- != 0) {
144: switch (style) {
145: case INVOKE_LATER:
146: synchronized (rqRable) {
147: System.out.println(" InvL #" + idx);
148: rq.invokeLater(rqRable);
149: System.out.println("Done InvL #" + idx);
150: rqRable.wait();
151: }
152: break;
153: case INVOKE_AND_WAIT:
154: System.out.println(" InvW #" + idx);
155: rq.invokeAndWait(rqRable);
156: System.out.println("Done InvW #" + idx);
157: break;
158: case PREEMPT_LATER:
159: synchronized (rqRable) {
160: System.out.println(" PreL #" + idx);
161: rq.preemptLater(rqRable);
162: System.out.println("Done PreL #" + idx);
163: rqRable.wait();
164: }
165: break;
166: case PREEMPT_AND_WAIT:
167: System.out.println(" PreW #" + idx);
168: rq.preemptAndWait(rqRable);
169: System.out.println("Done PreW #" + idx);
170: break;
171: }
172:
173: if (repeatDelay < 0)
174: break;
175: Thread.sleep(repeatDelay);
176: }
177: } catch (InterruptedException ie) {
178: }
179: synchronized (RunnableQueueTest.this ) {
180: activeThreads--;
181: RunnableQueueTest.this .notify();
182: }
183: }
184: }
185:
186: public static class RQRable implements Runnable {
187: int idx;
188: long dur;
189:
190: RQRable(int idx, long dur) {
191: this .idx = idx;
192: this .dur = dur;
193: }
194:
195: public void run() {
196: try {
197: System.out.println(" B Rable #" + idx);
198: Thread.sleep(dur);
199: System.out.println(" E Rable #" + idx);
200: synchronized (this ) {
201: notify();
202: }
203: } catch (InterruptedException ie) {
204: }
205: }
206: }
207:
208: public static void main(String[] args) {
209: RunnableQueueTest rqt = new RunnableQueueTest(20);
210: try {
211: rqt.runImpl();
212: } catch (Exception e) {
213: e.printStackTrace();
214: }
215: }
216: }
|