
Performance Cookbook: Inter-Thread communication in JMeter

Why?
Inter-Thread communication is often required to guarantee the test continuity. For multi-user-type scenarios, various users may need to pass around a few objects or identifiers, to be picked up by another user. A prime example would be an end user creating an order, while the store employee would have to pick up this order and process it for shipment.
If left unsupervised, at a large scale, the end users would fight over the same order visible from a page list, creating a race condition. The race occurs when two or more threads try to modify the same value, or when one thread tries to update any value when another tries to read it.
This might result in abnormal error rates. To avoid this problem the threads need some way to communicate and guarantee exclusive access to an identifier.
How to?
The simplified version of inter-thread communication is achievable with a simple property.
For multi-worker workloads, you’ll need a third party authority to avoid race conditions on cluster level.
For a Single Worker:
- Create StartUp thread group. This will guarantee your collection will get created only once.
- Under the Common Collections thread group, create a JSR223 sampler, using groovy
- In the sampler, create your collection of choice. For thread safety, refer to available collection types from java.util.concurrent library. Most common options will be:
java.util.concurrent.ConcurrentHashMap<>
java.util.concurrent.LinkedBlockingQueue<>
java.util.concurrent.CopyOnWriteArrayList<>
- put the reference of this object to JMeter’s properties
- In the producer thread, grab the reference to your collection and put a new object into the collection.
- In the consumer thread, grab the reference to the same collection and get the object produced by the producer from the collection.
SetUp Thread Group
import java.util.concurrent.ConcurrentLinkedQueue;
def commonQueue = new ConcurrentLinkedQueue<Object>(); //object instantiation
// it only gets invoked once
props.put(„commonQueue”, commonQueue); //store the object reference in the propertiesProducer Thread
//this could be a thread representing a customer placing an order.
def orderId = vars.get(„orderId”); //get the object you want to pass on to another thread
def orderCollection = props.get(„commonQueue”); //grab the collection reference
orderCollection.add(order); // add your order to the collectionConsumer Thread
//this might be a thread representing a user accepting or processing the order
Import java.util.concurrent.TimeUnit;
def orderCollection = props.get(„commonQueue”);
def orderId = orderCollection.poll(20, TimeUnit.SECONDS); //the thread will wait for 20 seconds for any message
If (null == orderId) { // in case no order arrived, a null value is returned
log.warn(„No new order has arrived for more than 20 seconds”);
ctx.setTestLogicalAction(org.apache.jmeter.threads.JMeterContext.TestLogicalAction.START_NEXT_ITERATION_OF_THREAD);
}How does it work?
Setting up a collection entity in the SetUp thread group guarantees only once execution. It is imperative no other thread in the test modifies the reference to this collection anywhere in the test. Each thread has access to the same test properties so the collection can be easily used by multiple thread groups.
Producer can easily access new items to the data structure of your choice, while the consumer can patiently wait for a signal that a new item of order had arrived.
The thread-safe data collection guarantee the data consistency across the test run.
What’s next?
For distributed tests, an in-memory object collection is not sufficient to guarantee no race conditions. The most flexible source of data would be a Postgres or a Redis database, where you can simulate both maps and queues.
The in-memory collections can also grow in size so make sure you create a sufficient number of consumers to consume the messages on time. If you want the objects to be persisted between test runs, you can serialise them in the TearDown thread group and load them in the SetUp thread group at test start up.
Alternatives:
The alternative would be the already available inter-thread communication plugin, but it only works with Strings so if you need to pass around complex objects or data structures and want to avid parsing them again, you’ll save yourself a lot of CPU cycles by just passing around a few pointers.
Share this content:
Ivan
I love your work Kuba, are you open for hire for trainings? In person or online?Thanks!
Perfluencer
That might be something I’ll consider in long term 🙂 thanks for dropping by!













2 comments