You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2009/04/18 14:38:20 UTC
svn commit: r766313 -
/jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
Author: sebb
Date: Sat Apr 18 12:38:19 2009
New Revision: 766313
URL: http://svn.apache.org/viewvc?rev=766313&view=rev
Log:
Confine threadContext to thread code
Document thread-safety of variables
Fix thread-safety bug in interrupt() method
Modified:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java?rev=766313&r1=766312&r2=766313&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java Sat Apr 18 12:38:19 2009
@@ -63,27 +63,33 @@
public class JMeterThread implements Runnable, Interruptible {
private static final Logger log = LoggingManager.getLoggerForClass();
- private int initialDelay = 0;
+ public static final String PACKAGE_OBJECT = "JMeterThread.pack"; // $NON-NLS-1$
- private Controller controller;
+ public static final String LAST_SAMPLE_OK = "JMeterThread.last_sample_ok"; // $NON-NLS-1$
- private volatile boolean running; // may be set from a different thread
+ private final Controller controller;
- private HashTree testTree;
+ private final HashTree testTree;
- private TestCompiler compiler;
+ private final TestCompiler compiler;
- private JMeterThreadMonitor monitor;
+ private final JMeterThreadMonitor monitor;
- private String threadName;
+ private final JMeterVariables threadVars;
- private JMeterContext threadContext;
+ private final Collection testListeners;
- private JMeterVariables threadVars;
+ private final ListenerNotifier notifier;
- private Collection testListeners;
+ /*
+ * The following variables are set by StandardJMeterEngine.
+ * This is done before start() is called, so the values will be published to the thread safely
+ * TODO - consider passing them to the constructor, so that they can be made final
+ * (to avoid adding lots of parameters, perhaps have a parameter wrapper object.
+ */
+ private String threadName;
- private ListenerNotifier notifier;
+ private int initialDelay = 0;
private int threadNum = 0;
@@ -92,24 +98,23 @@
private long endTime = 0;
private boolean scheduler = false;
-
// based on this scheduler is enabled or disabled
- private ThreadGroup threadGroup; // Gives access to parent thread
- // threadGroup
+ // Gives access to parent thread threadGroup
+ private ThreadGroup threadGroup;
private StandardJMeterEngine engine = null; // For access to stop methods.
- private boolean onErrorStopTest;
-
- private boolean onErrorStopThread;
+ /*
+ * The following variables may be set/read from multiple threads.
+ */
+ private volatile boolean running; // may be set from a different thread
- public static final String PACKAGE_OBJECT = "JMeterThread.pack"; // $NON-NLS-1$
+ private volatile boolean onErrorStopTest;
- public static final String LAST_SAMPLE_OK = "JMeterThread.last_sample_ok"; // $NON-NLS-1$
-
- public JMeterThread() {
- }
+ private volatile boolean onErrorStopThread;
+
+ private volatile Sampler currentSampler;
public JMeterThread(HashTree test, JMeterThreadMonitor monitor, ListenerNotifier note) {
this.monitor = monitor;
@@ -129,13 +134,6 @@
}
/**
- * Checks whether the JMeterThread is Scheduled.
- */
- public boolean isScheduled() {
- return this.scheduler;
- }
-
- /**
* Enable the scheduler for this JMeterThread.
*/
public void setScheduled(boolean sche) {
@@ -232,12 +230,14 @@
}
public void run() {
+ // threadContext is not thread-safe, so keep within thread
+ JMeterContext threadContext = JMeterContextService.getContext();
try {
- initRun();
+ initRun(threadContext);
while (running) {
Sampler sam;
while (running && (sam = controller.next()) != null) {
- process_sampler(sam, null);
+ process_sampler(sam, null, threadContext);
}
if (controller.isDone()) {
running = false;
@@ -269,12 +269,14 @@
*
* @param current sampler
* @param parent sampler
+ * @param threadContext
* @return SampleResult if a transaction was processed
*/
- private SampleResult process_sampler(Sampler current, Sampler parent) {
+ private SampleResult process_sampler(Sampler current, Sampler parent, JMeterContext threadContext) {
SampleResult transactionResult = null;
try {
threadContext.setCurrentSampler(current);
+ currentSampler = current;
// Check if we are running a transaction
TransactionSampler transactionSampler = null;
@@ -295,7 +297,7 @@
transactionResult.setAllThreads(JMeterContextService.getNumberOfThreads());
// Check assertions for the transaction sample
- checkAssertions(transactionPack.getAssertions(), transactionResult);
+ checkAssertions(transactionPack.getAssertions(), transactionResult, threadContext);
// Notify listeners with the transaction sample result
if (!(parent instanceof TransactionSampler)){
notifyListeners(transactionPack.getSampleListeners(), transactionResult);
@@ -309,8 +311,9 @@
// It is the sub sampler of the transaction that will be sampled
current = transactionSampler.getSubSampler();
if (current instanceof TransactionSampler){
- SampleResult res = process_sampler(current, prev);// recursive call
+ SampleResult res = process_sampler(current, prev, threadContext);// recursive call
threadContext.setCurrentSampler(prev);
+ currentSampler = prev;
current=null;
if (res!=null){
transactionSampler.addSubSamplerResult(res);
@@ -346,7 +349,7 @@
result.setThreadName(threadName);
threadContext.setPreviousResult(result);
runPostProcessors(pack.getPostProcessors());
- checkAssertions(pack.getAssertions(), result);
+ checkAssertions(pack.getAssertions(), result, threadContext);
// Do not send subsamples to listeners which receive the transaction sample
List sampleListeners = getSampleListeners(pack, transactionPack, transactionSampler);
notifyListeners(sampleListeners, result);
@@ -423,10 +426,10 @@
}
/**
+ * @param threadContext
*
*/
- protected void initRun() {
- threadContext = JMeterContextService.getContext();
+ private void initRun(JMeterContext threadContext) {
threadContext.setVariables(threadVars);
threadContext.setThreadNum(getThreadNum());
threadContext.getVariables().put(LAST_SAMPLE_OK, "true");
@@ -522,7 +525,7 @@
/** {@inheritDoc} */
public boolean interrupt(){
log.warn("Interrupting: " + threadName);
- Sampler samp = threadContext.getCurrentSampler();
+ Sampler samp = currentSampler; // fetch once
if (samp instanceof Interruptible){
try {
((Interruptible)samp).interrupt();
@@ -548,7 +551,7 @@
log.info("Stop Thread detected by thread: " + threadName);
}
- private void checkAssertions(List assertions, SampleResult parent) {
+ private void checkAssertions(List assertions, SampleResult parent, JMeterContext threadContext) {
Iterator iter = assertions.iterator();
while (iter.hasNext()) {
Assertion assertion = (Assertion) iter.next();
---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org