You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2017/11/15 22:33:59 UTC

svn commit: r1815393 - in /jmeter/trunk: src/core/org/apache/jmeter/gui/tree/JMeterTreeNode.java src/core/org/apache/jmeter/threads/JMeterThread.java src/core/org/apache/jmeter/threads/ThreadGroup.java xdocs/changes.xml

Author: pmouawad
Date: Wed Nov 15 22:33:59 2017
New Revision: 1815393

URL: http://svn.apache.org/viewvc?rev=1815393&view=rev
Log:
Utilising more modern Java, simplifying code and formatting code and comments
This closes #327 (PART 3)

Modified:
    jmeter/trunk/src/core/org/apache/jmeter/gui/tree/JMeterTreeNode.java
    jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
    jmeter/trunk/src/core/org/apache/jmeter/threads/ThreadGroup.java
    jmeter/trunk/xdocs/changes.xml

Modified: jmeter/trunk/src/core/org/apache/jmeter/gui/tree/JMeterTreeNode.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/tree/JMeterTreeNode.java?rev=1815393&r1=1815392&r2=1815393&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/tree/JMeterTreeNode.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/tree/JMeterTreeNode.java Wed Nov 15 22:33:59 2017
@@ -23,14 +23,14 @@ import java.beans.BeanInfo;
 import java.beans.IntrospectionException;
 import java.beans.Introspector;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Enumeration;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.swing.ImageIcon;
 import javax.swing.JPopupMenu;
 import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.TreeNode;
 
 import org.apache.jmeter.gui.GUIFactory;
 import org.apache.jmeter.gui.GuiPackage;
@@ -76,18 +76,14 @@ public class JMeterTreeNode extends Defa
      * @return {@link List} of {@link JMeterTreeNode}s
      */
     public List<JMeterTreeNode> getPathToThreadGroup() {
-        List<JMeterTreeNode> nodes = new ArrayList<>();
-        if (treeModel != null) {
-            TreeNode[] nodesToRoot = treeModel.getPathToRoot(this);
-            for (TreeNode node : nodesToRoot) {
-                JMeterTreeNode jMeterTreeNode = (JMeterTreeNode) node;
-                int level = jMeterTreeNode.getLevel();
-                if (level >= TEST_PLAN_LEVEL) {
-                    nodes.add(jMeterTreeNode);
-                }
-            }
+        if (treeModel == null) {
+            return new ArrayList<>();
         }
-        return nodes;
+
+        return Arrays.stream(treeModel.getPathToRoot(this))
+                .map(node -> (JMeterTreeNode) node)
+                .filter(node -> node.getLevel() >= TEST_PLAN_LEVEL)
+                .collect(Collectors.toList());
     }
     
     /**
@@ -95,7 +91,7 @@ public class JMeterTreeNode extends Defa
      * @param tagged The flag to be used for tagging
      */
     public void setMarkedBySearch(boolean tagged) {
-        if(this.markedBySearch == tagged) {
+        if (this.markedBySearch == tagged) {
             return;
         }
         this.markedBySearch = tagged;

Modified: jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java?rev=1815393&r1=1815392&r2=1815393&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java Wed Nov 15 22:33:59 2017
@@ -64,7 +64,6 @@ import org.slf4j.LoggerFactory;
 /**
  * The JMeter interface to the sampling process, allowing JMeter to see the
  * timing, add listeners for sampling events and to stop the sampling process.
- *
  */
 public class JMeterThread implements Runnable, Interruptible {
     private static final Logger log = LoggerFactory.getLogger(JMeterThread.class);
@@ -82,9 +81,7 @@ public class JMeterThread implements Run
     private static final float TIMER_FACTOR = JMeterUtils.getPropDefault("timer.factor", 1.0f);
 
     private static final TimerService TIMER_SERVICE = TimerService.getInstance();
-    /**
-     * 1 as float
-     */
+
     private static final float ONE_AS_FLOAT = 1.0f;
 
     private static final boolean APPLY_TIMER_FACTOR = Float.compare(TIMER_FACTOR,ONE_AS_FLOAT) != 0;
@@ -230,7 +227,6 @@ public class JMeterThread implements Run
 
     /**
      * Wait until the scheduled start time if necessary
-     *
      */
     private void startScheduler() {
         long delay = startTime - System.currentTimeMillis();
@@ -254,14 +250,13 @@ public class JMeterThread implements Run
                 while (running && sam != null) {
                     processSampler(sam, null, threadContext);
                     threadContext.cleanAfterSample();
-                    
+
                     // restart of the next loop 
                     // - was requested through threadContext
                     // - or the last sample failed AND the onErrorStartNextLoop option is enabled
-                    if(threadContext.isRestartNextLoop()
+                    if (threadContext.isRestartNextLoop()
                             || (onErrorStartNextLoop
-                                    && !TRUE.equals(threadContext.getVariables().get(LAST_SAMPLE_OK)))) 
-                    {
+                            && !TRUE.equals(threadContext.getVariables().get(LAST_SAMPLE_OK)))) {
                         if (log.isDebugEnabled() && onErrorStartNextLoop && !threadContext.isRestartNextLoop()) {
                             log.debug("StartNextLoop option is on, Last sample failed, starting next loop");
                         }
@@ -311,8 +306,7 @@ public class JMeterThread implements Run
                 threadFinished(iterationListener);
                 monitor.threadFinished(this); // Tell the monitor we are done
                 JMeterContextService.removeContext(); // Remove the ThreadLocal entry
-            }
-            finally {
+            } finally {
                 interruptLock.unlock(); // Allow any pending interrupt to complete (OK because currentSampler == null)
             }
         }
@@ -325,35 +319,36 @@ public class JMeterThread implements Run
      */
     private void triggerEndOfLoopOnParentControllers(Sampler sam, JMeterContext threadContext) {
         TransactionSampler transactionSampler = null;
-        if(sam instanceof TransactionSampler) {
+        if (sam instanceof TransactionSampler) {
             transactionSampler = (TransactionSampler) sam;
         }
 
         Sampler realSampler = findRealSampler(sam);
-        if(realSampler == null) {
-            throw new IllegalStateException("Got null subSampler calling findRealSampler for:"+
-                    (sam != null ? sam.getName(): "null")+", sam:"+sam);
+        if (realSampler == null) {
+            throw new IllegalStateException(
+                    "Got null subSampler calling findRealSampler for:" +
+                    (sam != null ? sam.getName() : "null") + ", sam:" + sam);
         }
         // Find parent controllers of current sampler
         FindTestElementsUpToRootTraverser pathToRootTraverser = new FindTestElementsUpToRootTraverser(realSampler);
         testTree.traverse(pathToRootTraverser);
-        
+
         // Trigger end of loop condition on all parent controllers of current sampler
         List<Controller> controllersToReinit = pathToRootTraverser.getControllersToRoot();
         for (Controller parentController : controllersToReinit) {
-            if(parentController instanceof AbstractThreadGroup) {
+            if (parentController instanceof AbstractThreadGroup) {
                 AbstractThreadGroup tg = (AbstractThreadGroup) parentController;
                 tg.startNextLoop();
             } else {
                 parentController.triggerEndOfLoop();
             }
         }
-        
+
         // bug 52968
         // When using Start Next Loop option combined to TransactionController.
         // if an error occurs in a Sample (child of TransactionController) 
         // then we still need to report the Transaction in error (and create the sample result)
-        if(transactionSampler != null) {
+        if (transactionSampler != null) {
             SamplePackage transactionPack = compiler.configureTransactionSampler(transactionSampler);
             doEndTransactionSampler(transactionSampler, null, transactionPack, threadContext);
         }
@@ -365,12 +360,11 @@ public class JMeterThread implements Run
      * if there are some other controllers (SimpleController or other implementations) between this TransactionSampler and the real sampler, 
      * triggerEndOfLoop will not be called for those controllers leaving them in "ugly" state.
      * the following method will try to find the sampler that really generate an error
-     * @param sampler
      * @return {@link Sampler}
      */
     private Sampler findRealSampler(Sampler sampler) {
         Sampler realSampler = sampler;
-        while(realSampler instanceof TransactionSampler) {
+        while (realSampler instanceof TransactionSampler) {
             realSampler = ((TransactionSampler) realSampler).getSubSampler();
         }
         return realSampler;
@@ -391,20 +385,19 @@ public class JMeterThread implements Run
         // Find the package for the transaction
         SamplePackage transactionPack = null;
         try {
-            if(current instanceof TransactionSampler) {
+            if (current instanceof TransactionSampler) {
                 transactionSampler = (TransactionSampler) current;
                 transactionPack = compiler.configureTransactionSampler(transactionSampler);
 
                 // Check if the transaction is done
-                if(transactionSampler.isTransactionDone()) {
-                    transactionResult = doEndTransactionSampler(transactionSampler, 
-                            parent, 
+                if (transactionSampler.isTransactionDone()) {
+                    transactionResult = doEndTransactionSampler(transactionSampler,
+                            parent,
                             transactionPack,
                             threadContext);
                     // Transaction is done, we do not have a sampler to sample
                     current = null;
-                }
-                else {
+                } else {
                     Sampler prev = current;
                     // It is the sub sampler of the transaction that will be sampled
                     current = transactionSampler.getSubSampler();
@@ -420,10 +413,10 @@ public class JMeterThread implements Run
             }
 
             // Check if we have a sampler to sample
-            if(current != null) {
+            if (current != null) {
                 executeSamplePackage(current, transactionSampler, transactionPack, threadContext);
             }
-            
+
             if (scheduler) {
                 // checks the scheduler to stop the iteration
                 stopSchedulerIfNeeded();
@@ -450,8 +443,8 @@ public class JMeterThread implements Run
                 log.error("Error while processing sampler.", e);
             }
         }
-        if(!running 
-                && transactionResult == null 
+        if (!running
+                && transactionResult == null
                 && transactionSampler != null
                 && transactionPack != null) {
             transactionResult = doEndTransactionSampler(transactionSampler, parent, transactionPack, threadContext);
@@ -468,7 +461,7 @@ public class JMeterThread implements Run
             TransactionSampler transactionSampler,
             SamplePackage transactionPack,
             JMeterContext threadContext) {
-        
+
         threadContext.setCurrentSampler(current);
         // Get the sampler ready to sample
         SamplePackage pack = compiler.configureSampler(current);
@@ -479,26 +472,26 @@ public class JMeterThread implements Run
 
         delay(pack.getTimers());
         SampleResult result = null;
-        if(running) {
+        if (running) {
             Sampler sampler = pack.getSampler();
             sampler.setThreadContext(threadContext);
             // TODO should this set the thread names for all the subsamples?
             // might be more efficient than fetching the name elsewhere
             sampler.setThreadName(threadName);
             TestBeanHelper.prepare(sampler);
-    
+
             // Perform the actual sample
             currentSampler = sampler;
-            if(!sampleMonitors.isEmpty()) {
-                for(SampleMonitor sampleMonitor : sampleMonitors) {
+            if (!sampleMonitors.isEmpty()) {
+                for (SampleMonitor sampleMonitor : sampleMonitors) {
                     sampleMonitor.sampleStarting(sampler);
                 }
             }
             try {
                 result = sampler.sample(null);
             } finally {
-                if(!sampleMonitors.isEmpty()) {
-                    for(SampleMonitor sampleMonitor : sampleMonitors) {
+                if (!sampleMonitors.isEmpty()) {
+                    for (SampleMonitor sampleMonitor : sampleMonitors) {
                         sampleMonitor.sampleEnded(sampler);
                     }
                 }
@@ -513,7 +506,7 @@ public class JMeterThread implements Run
             result.setAllThreads(nbTotalActiveThreads);
             result.setThreadName(threadName);
             SampleResult[] subResults = result.getSubResults();
-            if(subResults != null) {
+            if (subResults != null) {
                 for (SampleResult subResult : subResults) {
                     subResult.setGroupThreads(nbActiveThreadsInThreadGroup);
                     subResult.setAllThreads(nbTotalActiveThreads);
@@ -528,7 +521,7 @@ public class JMeterThread implements Run
             notifyListeners(sampleListeners, result);
             compiler.done(pack);
             // Add the result as subsample of transaction if we are in a transaction
-            if(transactionSampler != null) {
+            if (transactionSampler != null) {
                 transactionSampler.addSubSamplerResult(result);
             }
 
@@ -551,10 +544,8 @@ public class JMeterThread implements Run
     }
 
     private SampleResult doEndTransactionSampler(
-                            TransactionSampler transactionSampler, 
-                            Sampler parent,
-                            SamplePackage transactionPack,
-                            JMeterContext threadContext) {
+            TransactionSampler transactionSampler, Sampler parent,
+            SamplePackage transactionPack, JMeterContext threadContext) {
         // Get the transaction sample result
         SampleResult transactionResult = transactionSampler.getTransactionResult();
         transactionResult.setThreadName(threadName);
@@ -607,7 +598,7 @@ public class JMeterThread implements Run
 
     /**
      * @param threadContext
-     * @return the iteration listener 
+     * @return the iteration listener
      */
     private IterationListener initRun(JMeterContext threadContext) {
         threadContext.setVariables(threadVars);
@@ -784,13 +775,16 @@ public class JMeterThread implements Run
     private void checkAssertions(List<Assertion> assertions, SampleResult parent, JMeterContext threadContext) {
         for (Assertion assertion : assertions) {
             TestBeanHelper.prepare((TestElement) assertion);
-            if (assertion instanceof AbstractScopedAssertion){
+            if (assertion instanceof AbstractScopedAssertion) {
                 AbstractScopedAssertion scopedAssertion = (AbstractScopedAssertion) assertion;
                 String scope = scopedAssertion.fetchScope();
-                if (scopedAssertion.isScopeParent(scope) || scopedAssertion.isScopeAll(scope) || scopedAssertion.isScopeVariable(scope)){
+                if (scopedAssertion.isScopeParent(scope)
+                        || scopedAssertion.isScopeAll(scope)
+                        || scopedAssertion.isScopeVariable(scope)) {
                     processAssertion(parent, assertion);
                 }
-                if (scopedAssertion.isScopeChildren(scope) || scopedAssertion.isScopeAll(scope)){
+                if (scopedAssertion.isScopeChildren(scope)
+                        || scopedAssertion.isScopeAll(scope)) {
                     SampleResult[] children = parent.getSubResults();
                     boolean childError = false;
                     for (SampleResult childSampleResult : children) {
@@ -801,7 +795,7 @@ public class JMeterThread implements Run
                     }
                     // If parent is OK, but child failed, add a message and flag the parent as failed
                     if (childError && parent.isSuccessful()) {
-                        AssertionResult assertionResult = new AssertionResult(((AbstractTestElement)assertion).getName());
+                        AssertionResult assertionResult = new AssertionResult(((AbstractTestElement) assertion).getName());
                         assertionResult.setResultForFailure("One or more sub-samples failed");
                         parent.addAssertionResult(assertionResult);
                         parent.setSuccessful(false);
@@ -857,8 +851,7 @@ public class JMeterThread implements Run
         for (Timer timer : timers) {
             TestBeanHelper.prepare((TestElement) timer);
             long delay = timer.delay();
-            if(APPLY_TIMER_FACTOR && 
-                    timer.isModifiable()) {
+            if (APPLY_TIMER_FACTOR && timer.isModifiable()) {
                 if (log.isDebugEnabled()) {
                     log.debug("Applying TIMER_FACTOR:{} on timer:{} for thread:{}", TIMER_FACTOR,
                             ((TestElement) timer).getName(), getThreadName());
@@ -869,7 +862,7 @@ public class JMeterThread implements Run
         }
         if (totalDelay > 0) {
             try {
-                if(scheduler) {
+                if (scheduler) {
                     // We reduce pause to ensure end of test is not delayed by a sleep ending after test scheduled end
                     // See Bug 60049
                     totalDelay = TIMER_SERVICE.adjustDelay(totalDelay, endTime);
@@ -885,11 +878,9 @@ public class JMeterThread implements Run
     void notifyTestListeners() {
         threadVars.incIteration();
         for (TestIterationListener listener : testIterationStartListeners) {
+            listener.testIterationStart(new LoopIterationEvent(threadGroupLoopController, threadVars.getIteration()));
             if (listener instanceof TestElement) {
-                listener.testIterationStart(new LoopIterationEvent(threadGroupLoopController, threadVars.getIteration()));
                 ((TestElement) listener).recoverRunningVersion();
-            } else {
-                listener.testIterationStart(new LoopIterationEvent(threadGroupLoopController, threadVars.getIteration()));
             }
         }
     }
@@ -897,11 +888,11 @@ public class JMeterThread implements Run
     private void notifyListeners(List<SampleListener> listeners, SampleResult result) {
         SampleEvent event = new SampleEvent(result, threadGroup.getName(), threadVars);
         notifier.notifyListeners(event, listeners);
-
     }
 
     /**
      * Set rampup delay for JMeterThread Thread
+     *
      * @param delay Rampup delay for JMeterThread
      */
     public void setInitialDelay(int delay) {
@@ -917,8 +908,9 @@ public class JMeterThread implements Run
 
     /**
      * Wait for delay with RAMPUP_GRANULARITY
+     *
      * @param delay delay in ms
-     * @param type Delay type
+     * @param type  Delay type
      */
     protected final void delayBy(long delay, String type) {
         if (delay > 0) {
@@ -926,7 +918,7 @@ public class JMeterThread implements Run
             long end = start + delay;
             long now;
             long pause = RAMPUP_GRANULARITY;
-            while(running && (now = System.currentTimeMillis()) < end) {
+            while (running && (now = System.currentTimeMillis()) < end) {
                 long togo = end - now;
                 if (togo < pause) {
                     pause = togo;
@@ -957,8 +949,7 @@ public class JMeterThread implements Run
     /**
      * Sets the threadNum.
      *
-     * @param threadNum
-     *            the threadNum to set
+     * @param threadNum the threadNum to set
      */
     public void setThreadNum(int threadNum) {
         this.threadNum = threadNum;
@@ -986,8 +977,7 @@ public class JMeterThread implements Run
     /**
      * Should Test stop on sampler error?
      *
-     * @param b -
-     *            true or false
+     * @param b true or false
      */
     public void setOnErrorStopTest(boolean b) {
         onErrorStopTest = b;
@@ -996,8 +986,7 @@ public class JMeterThread implements Run
     /**
      * Should Test stop abruptly on sampler error?
      *
-     * @param b -
-     *            true or false
+     * @param b true or false
      */
     public void setOnErrorStopTestNow(boolean b) {
         onErrorStopTestNow = b;
@@ -1006,8 +995,7 @@ public class JMeterThread implements Run
     /**
      * Should Thread stop on Sampler error?
      *
-     * @param b -
-     *            true or false
+     * @param b true or false
      */
     public void setOnErrorStopThread(boolean b) {
         onErrorStopThread = b;
@@ -1016,8 +1004,7 @@ public class JMeterThread implements Run
     /**
      * Should Thread start next loop on Sampler error?
      *
-     * @param b -
-     *            true or false
+     * @param b true or false
      */
     public void setOnErrorStartNextLoop(boolean b) {
         onErrorStartNextLoop = b;

Modified: jmeter/trunk/src/core/org/apache/jmeter/threads/ThreadGroup.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/ThreadGroup.java?rev=1815393&r1=1815392&r2=1815393&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/threads/ThreadGroup.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/threads/ThreadGroup.java Wed Nov 15 22:33:59 2017
@@ -78,29 +78,19 @@ public class ThreadGroup extends Abstrac
     
     private transient Object addThreadLock = new Object();
 
-    /**
-     * Is test (still) running?
-     */
+    /** Is test (still) running? */
     private volatile boolean running = false;
 
-    /**
-     * Thread Group number
-     */
+    /** Thread Group number */
     private int groupNumber;
 
-    /**
-     * Are we using delayed startup?
-     */
+    /** Are we using delayed startup? */
     private boolean delayedStartup;
 
-    /**
-     * Thread safe class
-     */
+    /** Thread safe class */
     private ListenerNotifier notifier;
 
-    /**
-     * This property will be cloned
-     */
+    /** This property will be cloned */
     private ListedHashTree threadGroupTree;
 
     /**
@@ -197,24 +187,24 @@ public class ThreadGroup extends Abstrac
      */
     private void scheduleThread(JMeterThread thread, long now) {
 
-        // if true the Scheduler is enabled
-        if (getScheduler()) {
-            // set the start time for the Thread
-            if (getDelay() >= 0) {// Duration is in seconds
-                thread.setStartTime(getDelay() * 1000 + now);
-            } else {
-                throw new JMeterStopTestException("Invalid delay "+getDelay()+" set in Thread Group:"+getName());
-            }
+        if (!getScheduler()) { // if the Scheduler is not enabled
+            return;
+        }
 
-            // set the endtime for the Thread
-            if (getDuration() > 0) {// Duration is in seconds
-                thread.setEndTime(getDuration() * 1000 + (thread.getStartTime()));
-            } else {
-                throw new JMeterStopTestException("Invalid duration "+getDuration()+" set in Thread Group:"+getName());
-            }
-            // Enables the scheduler
-            thread.setScheduled(true);
+        if (getDelay() >= 0) { // Duration is in seconds
+            thread.setStartTime(getDelay() * 1000 + now);
+        } else {
+            throw new JMeterStopTestException("Invalid delay " + getDelay() + " set in Thread Group:" + getName());
         }
+
+        // set the endtime for the Thread
+        if (getDuration() > 0) {// Duration is in seconds
+            thread.setEndTime(getDuration() * 1000 + (thread.getStartTime()));
+        } else {
+            throw new JMeterStopTestException("Invalid duration " + getDuration() + " set in Thread Group:" + getName());
+        }
+        // Enables the scheduler
+        thread.setScheduled(true);
     }
 
     @Override
@@ -345,10 +335,10 @@ public class ThreadGroup extends Abstrac
      */
     @Override
     public boolean stopThread(String threadName, boolean now) {
-        for(Entry<JMeterThread, Thread> entry : allThreads.entrySet()) {
-            JMeterThread thrd = entry.getKey();
-            if (thrd.getThreadName().equals(threadName)) {
-                stopThread(thrd, entry.getValue(), now);
+        for (Entry<JMeterThread, Thread> threadEntry : allThreads.entrySet()) {
+            JMeterThread jMeterThread = threadEntry.getKey();
+            if (jMeterThread.getThreadName().equals(threadName)) {
+                stopThread(jMeterThread, threadEntry.getValue(), now);
                 return true;
             }
         }
@@ -398,10 +388,8 @@ public class ThreadGroup extends Abstrac
                 log.warn("Exception occurred interrupting ThreadStarter", e);
             }
         }
-        
-        for (Entry<JMeterThread, Thread> entry : allThreads.entrySet()) {
-            stopThread(entry.getKey(), entry.getValue(), true);
-        }
+
+        allThreads.forEach((key, value) -> stopThread(key, value, true));
     }
 
 
@@ -421,9 +409,7 @@ public class ThreadGroup extends Abstrac
                 log.warn("Exception occurred interrupting ThreadStarter", e);
             }            
         }
-        for (JMeterThread item : allThreads.keySet()) {
-            item.stop();
-        }
+        allThreads.keySet().forEach(JMeterThread::stop);
     }
 
     /**
@@ -481,13 +467,11 @@ public class ThreadGroup extends Abstrac
             waitThreadStopped(threadStarter);
         }
         /* @Bugzilla 60933
-         * Like threads can be added on the fly during a test into allThreads
-         * we have to check if allThreads is rly empty before stop 
+         * Threads can be added on the fly during a test into allThreads
+         * we have to check if allThreads is really empty before stopping
          */
-        while ( !allThreads.isEmpty() ) {
-            for (Thread t : allThreads.values()) {
-                waitThreadStopped(t);
-            }
+        while (!allThreads.isEmpty()) {
+            allThreads.values().forEach(this::waitThreadStopped);
         }   
       
     }
@@ -497,13 +481,14 @@ public class ThreadGroup extends Abstrac
      * @param thread Thread
      */
     private void waitThreadStopped(Thread thread) {
-        if (thread != null) {
-            while (thread.isAlive()) {
-                try {
-                    thread.join(WAIT_TO_DIE);
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                }
+        if (thread == null) {
+            return;
+        }
+        while (thread.isAlive()) {
+            try {
+                thread.join(WAIT_TO_DIE);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
             }
         }
     }
@@ -547,10 +532,8 @@ public class ThreadGroup extends Abstrac
             this.engine = engine;
             // Store context from Root Thread to pass it to created threads
             this.context = JMeterContextService.getContext();
-            
         }
         
-
         /**
          * Wait for delay with RAMPUP_GRANULARITY
          * @param delay delay in ms

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1815393&r1=1815392&r2=1815393&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Wed Nov 15 22:33:59 2017
@@ -162,7 +162,6 @@ Summary
     <li><bug>61697</bug>Introduce Darcula Look And Feel to make JMeter UI more attractive</li>
     <li><bug>61704</bug>Toolbar : Improve a bit the right part</li>
     <li><bug>61731</bug>Enhance Test plan Backup with option to save before run. Based on a contribution by orimarko at gmail.com</li>
-    <li><pr>324</pr> Save backup refactor. Contributed by Graham Russell (graham at ham1.co.uk)</li>
 </ul>
 
 <ch_section>Non-functional changes</ch_section>
@@ -176,6 +175,8 @@ Summary
     <li><pr>319</pr>Removed commented out code. Contributed by Graham Russell (graham at ham1.co.uk)</li>
     <li><pr>322</pr>General JavaDoc cleanup. Contributed by Graham Russell (graham at ham1.co.uk)</li>
     <li><pr>323</pr>Extracted method and used streams to improve readability. Contributed by Graham Russell (graham at ham1.co.uk)</li>
+    <li><pr>324</pr> Save backup refactor. Contributed by Graham Russell (graham at ham1.co.uk)</li>
+    <li><pr>327</pr> Utilising more modern Java, simplifying code and formatting code and comments. Contributed by Graham Russell (graham at ham1.co.uk)</li>
 </ul>
 
  <!-- =================== Bug fixes =================== -->