Lines 33-38
Link Here
|
33 |
import java.util.List; |
33 |
import java.util.List; |
34 |
import java.util.Map; |
34 |
import java.util.Map; |
35 |
import java.util.Properties; |
35 |
import java.util.Properties; |
|
|
36 |
import java.util.concurrent.Executors; |
37 |
import java.util.concurrent.Future; |
38 |
import java.util.concurrent.ScheduledExecutorService; |
39 |
import java.util.concurrent.TimeUnit; |
36 |
|
40 |
|
37 |
import org.apache.jmeter.JMeter; |
41 |
import org.apache.jmeter.JMeter; |
38 |
import org.apache.jmeter.testbeans.TestBean; |
42 |
import org.apache.jmeter.testbeans.TestBean; |
Lines 93-99
Link Here
|
93 |
private static final List<TestListener> testList = new ArrayList<TestListener>(); |
97 |
private static final List<TestListener> testList = new ArrayList<TestListener>(); |
94 |
|
98 |
|
95 |
/** JMeterThread => its JVM thread */ |
99 |
/** JMeterThread => its JVM thread */ |
96 |
private final Map<JMeterThread, Thread> allThreads; |
100 |
private final Map<JMeterThread, Future<?>> allThreads; |
97 |
|
101 |
|
98 |
/** flag to show that groups are still being created, i.e test plan is not complete */ |
102 |
/** flag to show that groups are still being created, i.e test plan is not complete */ |
99 |
private volatile boolean startingGroups; |
103 |
private volatile boolean startingGroups; |
Lines 106-111
Link Here
|
106 |
|
110 |
|
107 |
private HashTree test; |
111 |
private HashTree test; |
108 |
|
112 |
|
|
|
113 |
private ScheduledExecutorService mThreadPool; |
114 |
|
109 |
private volatile SearchByClass testListenersSave; |
115 |
private volatile SearchByClass testListenersSave; |
110 |
|
116 |
|
111 |
private final String host; |
117 |
private final String host; |
Lines 152-160
Link Here
|
152 |
thrd.stop(); |
158 |
thrd.stop(); |
153 |
thrd.interrupt(); |
159 |
thrd.interrupt(); |
154 |
if (now) { |
160 |
if (now) { |
155 |
Thread t = engine.allThreads.get(thrd); |
161 |
Future<?> t = engine.allThreads.get(thrd); |
156 |
if (t != null) { |
162 |
if (t != null) { |
157 |
t.interrupt(); |
163 |
t.cancel(true); |
158 |
} |
164 |
} |
159 |
} |
165 |
} |
160 |
return true; |
166 |
return true; |
Lines 170-176
Link Here
|
170 |
|
176 |
|
171 |
public StandardJMeterEngine(String host) { |
177 |
public StandardJMeterEngine(String host) { |
172 |
this.host = host; |
178 |
this.host = host; |
173 |
this.allThreads = Collections.synchronizedMap(new HashMap<JMeterThread, Thread>()); |
179 |
this.allThreads = Collections.synchronizedMap(new HashMap<JMeterThread, Future<?>>()); |
174 |
// Hack to allow external control |
180 |
// Hack to allow external control |
175 |
engine = this; |
181 |
engine = this; |
176 |
} |
182 |
} |
Lines 425-430
Link Here
|
425 |
// and the listeners, and the timer |
431 |
// and the listeners, and the timer |
426 |
Iterator<ThreadGroup> iter = searcher.getSearchResults().iterator(); |
432 |
Iterator<ThreadGroup> iter = searcher.getSearchResults().iterator(); |
427 |
|
433 |
|
|
|
434 |
int threadPoolSize = JMeterUtils.getPropDefault("threadPoolSize", 1000); |
435 |
log.debug("thread pool size is " + threadPoolSize); |
436 |
mThreadPool = Executors.newScheduledThreadPool(threadPoolSize); |
437 |
|
428 |
/* |
438 |
/* |
429 |
* Here's where the test really starts. Run a Full GC now: it's no harm |
439 |
* Here's where the test really starts. Run a Full GC now: it's no harm |
430 |
* at all (just delays test start by a tiny amount) and hitting one too |
440 |
* at all (just delays test start by a tiny amount) and hitting one too |
Lines 468-489
Link Here
|
468 |
jmeterThread.setThreadNum(i); |
478 |
jmeterThread.setThreadNum(i); |
469 |
jmeterThread.setThreadGroup(group); |
479 |
jmeterThread.setThreadGroup(group); |
470 |
jmeterThread.setInitialContext(JMeterContextService.getContext()); |
480 |
jmeterThread.setInitialContext(JMeterContextService.getContext()); |
471 |
jmeterThread.setInitialDelay((int) (perThreadDelay * i)); |
|
|
472 |
final String threadName = groupName + " " + (groupCount) + "-" + (i + 1); |
481 |
final String threadName = groupName + " " + (groupCount) + "-" + (i + 1); |
473 |
jmeterThread.setThreadName(threadName); |
482 |
jmeterThread.setThreadName(threadName); |
474 |
|
483 |
|
475 |
scheduleThread(jmeterThread, group); |
|
|
476 |
|
477 |
// Set up variables for stop handling |
484 |
// Set up variables for stop handling |
478 |
jmeterThread.setEngine(this); |
485 |
jmeterThread.setEngine(this); |
479 |
jmeterThread.setOnErrorStopTest(onErrorStopTest); |
486 |
jmeterThread.setOnErrorStopTest(onErrorStopTest); |
480 |
jmeterThread.setOnErrorStopTestNow(onErrorStopTestNow); |
487 |
jmeterThread.setOnErrorStopTestNow(onErrorStopTestNow); |
481 |
jmeterThread.setOnErrorStopThread(onErrorStopThread); |
488 |
jmeterThread.setOnErrorStopThread(onErrorStopThread); |
482 |
|
489 |
|
483 |
Thread newThread = new Thread(jmeterThread); |
490 |
jmeterThread.initRun(); |
484 |
newThread.setName(threadName); |
491 |
Future<?> future = scheduleThread(jmeterThread, group, (int)perThreadDelay*i); |
485 |
allThreads.put(jmeterThread, newThread); |
492 |
allThreads.put(jmeterThread, future); |
486 |
newThread.start(); |
|
|
487 |
} // end of thread startup for this thread group |
493 |
} // end of thread startup for this thread group |
488 |
if (serialized && iter.hasNext()) { |
494 |
if (serialized && iter.hasNext()) { |
489 |
log.info("Waiting for thread group: "+groupName+" to finish before starting next group"); |
495 |
log.info("Waiting for thread group: "+groupName+" to finish before starting next group"); |
Lines 506-560
Link Here
|
506 |
* @param thread |
512 |
* @param thread |
507 |
* @param group |
513 |
* @param group |
508 |
*/ |
514 |
*/ |
509 |
private void scheduleThread(JMeterThread thread, ThreadGroup group) { |
515 |
private Future<?> scheduleThread(JMeterThread thread, ThreadGroup group, int delay) { |
510 |
// if true the Scheduler is enabled |
516 |
// if true the Scheduler is enabled |
511 |
if (group.getScheduler()) { |
517 |
return mThreadPool.schedule(thread, delay, TimeUnit.MILLISECONDS); |
512 |
long now = System.currentTimeMillis(); |
|
|
513 |
// set the start time for the Thread |
514 |
if (group.getDelay() > 0) {// Duration is in seconds |
515 |
thread.setStartTime(group.getDelay() * 1000 + now); |
516 |
} else { |
517 |
long start = group.getStartTime(); |
518 |
if (start < now) { |
519 |
start = now; // Force a sensible start time |
520 |
} |
521 |
thread.setStartTime(start); |
522 |
} |
523 |
|
524 |
// set the endtime for the Thread |
525 |
if (group.getDuration() > 0) {// Duration is in seconds |
526 |
thread.setEndTime(group.getDuration() * 1000 + (thread.getStartTime())); |
527 |
} else { |
528 |
thread.setEndTime(group.getEndTime()); |
529 |
} |
530 |
|
531 |
// Enables the scheduler |
532 |
thread.setScheduled(true); |
533 |
} |
534 |
} |
518 |
} |
535 |
|
519 |
|
536 |
private boolean verifyThreadsStopped() { |
520 |
private boolean verifyThreadsStopped() { |
537 |
boolean stoppedAll = true; |
521 |
boolean stoppedAll = true; |
538 |
List<Thread> threadsToCheck = new ArrayList<Thread>(allThreads.size()); |
522 |
List<Future<?>> threadsToCheck = new ArrayList<Future<?>>(allThreads.size()); |
539 |
synchronized (allThreads) { // Protect iterator |
523 |
synchronized (allThreads) { // Protect iterator |
540 |
Iterator<JMeterThread> iter = allThreads.keySet().iterator(); |
524 |
Iterator<JMeterThread> iter = allThreads.keySet().iterator(); |
541 |
while (iter.hasNext()) { |
525 |
while (iter.hasNext()) { |
542 |
Thread t = allThreads.get(iter.next()); |
526 |
Future<?> t = allThreads.get(iter.next()); |
543 |
if (t != null) { |
527 |
if (t != null) { |
544 |
threadsToCheck.add(t); // Do work later to reduce time in synch block. |
528 |
threadsToCheck.add(t); // Do work later to reduce time in synch block. |
545 |
} |
529 |
} |
546 |
} |
530 |
} |
547 |
} |
531 |
} |
548 |
for(int i=0; i < threadsToCheck.size(); i++) { |
532 |
for(int i=0; i < threadsToCheck.size(); i++) { |
549 |
Thread t = threadsToCheck.get(i); |
533 |
Future<?> t = threadsToCheck.get(i); |
550 |
if (t.isAlive()) { |
534 |
if (t.isCancelled() || t.isDone()) { |
551 |
try { |
535 |
t.cancel(true); |
552 |
t.join(WAIT_TO_DIE); |
536 |
if (t.isCancelled() || t.isDone()) { |
553 |
} catch (InterruptedException e) { |
|
|
554 |
} |
555 |
if (t.isAlive()) { |
556 |
stoppedAll = false; |
537 |
stoppedAll = false; |
557 |
log.warn("Thread won't exit: " + t.getName()); |
538 |
log.warn("Thread won't exit: " + t); |
558 |
} |
539 |
} |
559 |
} |
540 |
} |
560 |
} |
541 |
} |
Lines 568-575
Link Here
|
568 |
JMeterThread item = iter.next(); |
549 |
JMeterThread item = iter.next(); |
569 |
item.stop(); // set stop flag |
550 |
item.stop(); // set stop flag |
570 |
item.interrupt(); // interrupt sampler if possible |
551 |
item.interrupt(); // interrupt sampler if possible |
571 |
Thread t = allThreads.get(item); |
552 |
Future<?> t = allThreads.get(item); |
572 |
t.interrupt(); // also interrupt JVM thread |
553 |
t.cancel(true);// also interrupt JVM thread |
573 |
} |
554 |
} |
574 |
} |
555 |
} |
575 |
} |
556 |
} |