View | Details | Raw Unified | Return to bug 60530
Collapse All | Expand All

(-)src/core/org/apache/jmeter/threads/AbstractThreadGroup.java (+2 lines)
Lines 251-256 Link Here
251
251
252
    public abstract void start(int groupCount, ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine);
252
    public abstract void start(int groupCount, ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine);
253
253
254
    public abstract JMeterThread addNewThread(int delay, StandardJMeterEngine engine);
255
254
    public abstract boolean verifyThreadsStopped();
256
    public abstract boolean verifyThreadsStopped();
255
257
256
    public abstract void waitThreadsStopped();
258
    public abstract void waitThreadsStopped();
(-)src/core/org/apache/jmeter/threads/JMeterThread.java (+9 lines)
Lines 50-55 Link Here
50
import org.apache.jmeter.util.JMeterUtils;
50
import org.apache.jmeter.util.JMeterUtils;
51
import org.apache.jorphan.collections.HashTree;
51
import org.apache.jorphan.collections.HashTree;
52
import org.apache.jorphan.collections.HashTreeTraverser;
52
import org.apache.jorphan.collections.HashTreeTraverser;
53
import org.apache.jorphan.collections.ListedHashTree;
53
import org.apache.jorphan.collections.SearchByClass;
54
import org.apache.jorphan.collections.SearchByClass;
54
import org.apache.jorphan.logging.LoggingManager;
55
import org.apache.jorphan.logging.LoggingManager;
55
import org.apache.jorphan.util.JMeterError;
56
import org.apache.jorphan.util.JMeterError;
Lines 977-980 Link Here
977
        this.threadGroup = group;
978
        this.threadGroup = group;
978
    }
979
    }
979
980
981
    public ListedHashTree getTestTree() {
982
        return (ListedHashTree) testTree;
983
    }
984
985
    public ListenerNotifier getNotifier() {
986
        return notifier;
987
    }
988
980
}
989
}
(-)src/core/org/apache/jmeter/threads/ThreadGroup.java (-17 / +45 lines)
Lines 83-99 Link Here
83
83
84
    // List of active threads
84
    // List of active threads
85
    private final Map<JMeterThread, Thread> allThreads = new ConcurrentHashMap<>();
85
    private final Map<JMeterThread, Thread> allThreads = new ConcurrentHashMap<>();
86
    private final Object addThreadLock = new Object();
86
87
87
    /**
88
    /**
88
     * Is test (still) running?
89
     * Is test (still) running?
89
     */
90
     */
90
    private volatile boolean running = false;
91
    private volatile boolean running = false;
91
92
93
    private int groupNumber;
94
92
    /**
95
    /**
93
     * Are we using delayed startup?
96
     * Are we using delayed startup?
94
     */
97
     */
95
    private boolean delayedStartup;
98
    private boolean delayedStartup;
96
99
100
    private ListenerNotifier notifier;
101
102
    private ListedHashTree threadGroupTree;
103
97
    /**
104
    /**
98
     * No-arg constructor.
105
     * No-arg constructor.
99
     */
106
     */
Lines 257-294 Link Here
257
    }
264
    }
258
265
259
    @Override
266
    @Override
260
    public void start(int groupCount, ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine) {
267
    public void start(int groupNum, ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine) {
261
        running = true;
268
        running = true;
269
        groupNumber = groupNum;
270
        this.notifier = notifier;
271
        this.threadGroupTree = threadGroupTree;
262
        int numThreads = getNumThreads();
272
        int numThreads = getNumThreads();
263
        int rampUpPeriodInSeconds = getRampUp();
273
        int rampUpPeriodInSeconds = getRampUp();
264
        float perThreadDelayInMillis = (float) (rampUpPeriodInSeconds * 1000) / (float) getNumThreads();
274
        float perThreadDelayInMillis = (float) (rampUpPeriodInSeconds * 1000) / (float) getNumThreads();
265
275
266
        delayedStartup = isDelayedStartup(); // Fetch once; needs to stay constant
276
        delayedStartup = isDelayedStartup(); // Fetch once; needs to stay constant
267
        log.info("Starting thread group number " + groupCount
277
        log.info("Starting thread group number " + groupNumber
268
                + " threads " + numThreads
278
                + " threads " + numThreads
269
                + " ramp-up " + rampUpPeriodInSeconds
279
                + " ramp-up " + rampUpPeriodInSeconds
270
                + " perThread " + perThreadDelayInMillis
280
                + " perThread " + perThreadDelayInMillis
271
                + " delayedStart=" + delayedStartup);
281
                + " delayedStart=" + delayedStartup);
272
        if (delayedStartup) {
282
        if (delayedStartup) {
273
            threadStarter = new Thread(new ThreadStarter(groupCount, notifier, threadGroupTree, engine), getName()+"-ThreadStarter");
283
            threadStarter = new Thread(new ThreadStarter(notifier, threadGroupTree, engine), getName()+"-ThreadStarter");
274
            threadStarter.setDaemon(true);
284
            threadStarter.setDaemon(true);
275
            threadStarter.start();
285
            threadStarter.start();
276
            // N.B. we don't wait for the thread to complete, as that would prevent parallel TGs
286
            // N.B. we don't wait for the thread to complete, as that would prevent parallel TGs
277
        } else {
287
        } else {
278
            long now = System.currentTimeMillis(); // needs to be same time for all threads in the group
288
            long now = System.currentTimeMillis(); // needs to be same time for all threads in the group
279
            final JMeterContext context = JMeterContextService.getContext();
289
            final JMeterContext context = JMeterContextService.getContext();
280
            for (int i = 0; running && i < numThreads; i++) {
290
            for (int threadNum = 0; running && threadNum < numThreads; threadNum++) {
281
                JMeterThread jmThread = makeThread(groupCount, notifier, threadGroupTree, engine, i, context);
291
                startNewThread(notifier, threadGroupTree, engine, threadNum, context, now, (int)(threadNum * perThreadDelayInMillis));
282
                scheduleThread(jmThread, now); // set start and end time
283
                jmThread.setInitialDelay((int)(i * perThreadDelayInMillis));
284
                Thread newThread = new Thread(jmThread, jmThread.getThreadName());
285
                registerStartedThread(jmThread, newThread);
286
                newThread.start();
287
            }
292
            }
288
        }
293
        }
289
        log.info("Started thread group number "+groupCount);
294
        log.info("Started thread group number "+groupNumber);
290
    }
295
    }
291
296
297
    private JMeterThread startNewThread(ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine,
298
            int threadNum, final JMeterContext context, long now, int delay) {
299
        JMeterThread jmThread = makeThread(notifier, threadGroupTree, engine, threadNum, context);
300
        scheduleThread(jmThread, now); // set start and end time
301
        jmThread.setInitialDelay(delay);
302
        Thread newThread = new Thread(jmThread, jmThread.getThreadName());
303
        registerStartedThread(jmThread, newThread);
304
        newThread.start();
305
        return jmThread;
306
    }
292
    /**
307
    /**
293
     * Register Thread when it starts
308
     * Register Thread when it starts
294
     * @param jMeterThread {@link JMeterThread}
309
     * @param jMeterThread {@link JMeterThread}
Lines 298-304 Link Here
298
        allThreads.put(jMeterThread, newThread);
313
        allThreads.put(jMeterThread, newThread);
299
    }
314
    }
300
315
301
    private JMeterThread makeThread(int groupCount,
316
    private JMeterThread makeThread(
302
            ListenerNotifier notifier, ListedHashTree threadGroupTree,
317
            ListenerNotifier notifier, ListedHashTree threadGroupTree,
303
            StandardJMeterEngine engine, int i, 
318
            StandardJMeterEngine engine, int i, 
304
            JMeterContext context) { // N.B. Context needs to be fetched in the correct thread
319
            JMeterContext context) { // N.B. Context needs to be fetched in the correct thread
Lines 311-317 Link Here
311
        jmeterThread.setThreadNum(i);
326
        jmeterThread.setThreadNum(i);
312
        jmeterThread.setThreadGroup(this);
327
        jmeterThread.setThreadGroup(this);
313
        jmeterThread.setInitialContext(context);
328
        jmeterThread.setInitialContext(context);
314
        final String threadName = groupName + " " + (groupCount) + "-" + (i + 1);
329
        final String threadName = groupName + " " + groupNumber + "-" + (i + 1);
315
        jmeterThread.setThreadName(threadName);
330
        jmeterThread.setThreadName(threadName);
316
        jmeterThread.setEngine(engine);
331
        jmeterThread.setEngine(engine);
317
        jmeterThread.setOnErrorStopTest(onErrorStopTest);
332
        jmeterThread.setOnErrorStopTest(onErrorStopTest);
Lines 321-326 Link Here
321
        return jmeterThread;
336
        return jmeterThread;
322
    }
337
    }
323
338
339
    @Override
340
    public JMeterThread addNewThread(int delay, StandardJMeterEngine engine) {
341
        long now = System.currentTimeMillis();
342
        JMeterContext context = JMeterContextService.getContext();
343
        JMeterThread newJmThread;
344
        synchronized (addThreadLock) {
345
            int numThreads = getNumThreads();
346
            newJmThread = startNewThread(notifier, threadGroupTree, engine, numThreads, context, now, delay);
347
            setNumThreads(numThreads + 1);
348
        }
349
        JMeterContextService.addTotalThreads( 1 );
350
        log.info("Started new thread in group " + groupNumber );
351
        return newJmThread;
352
    }
353
324
    /**
354
    /**
325
     * Stop thread called threadName:
355
     * Stop thread called threadName:
326
     * <ol>
356
     * <ol>
Lines 504-518 Link Here
504
     */
534
     */
505
    class ThreadStarter implements Runnable {
535
    class ThreadStarter implements Runnable {
506
536
507
        private final int groupCount;
508
        private final ListenerNotifier notifier;
537
        private final ListenerNotifier notifier;
509
        private final ListedHashTree threadGroupTree;
538
        private final ListedHashTree threadGroupTree;
510
        private final StandardJMeterEngine engine;
539
        private final StandardJMeterEngine engine;
511
        private final JMeterContext context;
540
        private final JMeterContext context;
512
541
513
        public ThreadStarter(int groupCount, ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine) {
542
        public ThreadStarter(ListenerNotifier notifier, ListedHashTree threadGroupTree, StandardJMeterEngine engine) {
514
            super();
543
            super();
515
            this.groupCount = groupCount;
516
            this.notifier = notifier;
544
            this.notifier = notifier;
517
            this.threadGroupTree = threadGroupTree;
545
            this.threadGroupTree = threadGroupTree;
518
            this.engine = engine;
546
            this.engine = engine;
Lines 584-590 Link Here
584
                    if (usingScheduler && System.currentTimeMillis() > endtime) {
612
                    if (usingScheduler && System.currentTimeMillis() > endtime) {
585
                        break; // no point continuing beyond the end time
613
                        break; // no point continuing beyond the end time
586
                    }
614
                    }
587
                    JMeterThread jmThread = makeThread(groupCount, notifier, threadGroupTree, engine, i, context);
615
                    JMeterThread jmThread = makeThread(notifier, threadGroupTree, engine, i, context);
588
                    jmThread.setInitialDelay(0);   // Already waited
616
                    jmThread.setInitialDelay(0);   // Already waited
589
                    if (usingScheduler) {
617
                    if (usingScheduler) {
590
                        jmThread.setScheduled(true);
618
                        jmThread.setScheduled(true);

Return to bug 60530