{"id":43750,"date":"2015-09-16T19:36:45","date_gmt":"2015-09-16T16:36:45","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=43750"},"modified":"2023-12-13T11:52:50","modified_gmt":"2023-12-13T09:52:50","slug":"testing-concurrent-applications","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html","title":{"rendered":"Testing Concurrent Applications"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/java-concurrency-essentials.html\">Java Concurrency Essentials<\/a>.<\/p>\n<p>In this course, you will dive into the magic of concurrency. You will be introduced to the fundamentals of concurrency and concurrent code and you will learn about concepts like atomicity, synchronization and thread safety. Check it out <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/java-concurrency-essentials.html\">here<\/a>!<\/em><\/p>\n<div class=\"toc\">\n<h4>Table Of Contents<\/h4>\n<dl>\n<dt><a href=\"#intro\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#SimpleBlockingQueue\">2. SimpleBlockingQueue<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#test_blocking\">2.1. Test blocking operations<\/a><\/dt>\n<dt><a href=\"#test_correctness\">2.2. Testing for correctness<\/a><\/dt>\n<dt><a href=\"#test_perf\">2.3. Testing performance<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#frameworks\">3. Testing frameworks<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#jmock\">3.1. JMock<\/a><\/dt>\n<dt><a href=\"#groboutils\">3.2. Grobo Utils<\/a><\/dt>\n<\/dl>\n<\/dd>\n<\/dl>\n<\/div>\n<h2><a name=\"intro\"><\/a>1. Introduction<\/h2>\n<p>This article provides an introduction into the testing of multi-threaded applications. We implement a simple blocking queue and test its blocking behavior as well as its behavior and performance under stress test conditions. Finally we shed some light on available frameworks for unit testing of multi-threaded classes.<\/p>\n<h2><a name=\"SimpleBlockingQueue\"><\/a>2. SimpleBlockingQueue<\/h2>\n<p>In this section we are going to implement a very basic and simple blocking <code>Queue<\/code>. This queue should do nothing more than hold the elements we have put into it and give them back when calling <code>get()<\/code>. The <code>get()<\/code> should block until a new element is available.<\/p>\n<p>It is clear that the <code>java.util.concurrent<\/code> package already provides such functionality and that there is no need to implement this again, but for demonstration purposes we do it here in order to show how to test such a class.<\/p>\n<p>As backing data structure for our queue we choose a standard <code>LinkedList<\/code> from the <code>java.util<\/code> package. This list is not synchronized and call its <code>get()<\/code> method does not block. Hence we have to synchronized access to the list and we have to add the blocking functionality. The latter can be implemented with a simple <code>while()<\/code> loop that calls the <code>wait()<\/code> method on the list, when the queue is empty. If the queue is not empty, it returns the first element:<\/p>\n<pre class=\"brush:java\">\npublic class SimpleBlockingQueue&lt;T&gt; {\n\tprivate List&lt;T&gt; queue = new LinkedList&lt;T&gt;();\n\n\tpublic int getSize() {\n\t\tsynchronized(queue) {\n\t\t\treturn queue.size();\n\t\t}\n\t}\n\t\n\tpublic void put(T obj) {\n\t\tsynchronized(queue) {\n\t\t\tqueue.add(obj);\n\t\t\tqueue.notify();\n\t\t}\n\t}\n\t\n\tpublic T get() throws InterruptedException  {\n\t\twhile(true) {\n\t\t\tsynchronized(queue) {\n\t\t\t\tif(queue.isEmpty()) {\n\t\t\t\t\tqueue.wait();\n\t\t\t\t} else {\n\t\t\t\t\treturn queue.remove(0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n<\/pre>\n<h3><a name=\"test_blocking\"><\/a>2.1. Test blocking operations<\/h3>\n<p>Although this implementation is very simple, it is not that easy to test all the functionality, especially the blocking feature. When we just call <code>get()<\/code> on an empty queue, the current thread is blocked until another threads inserts a new item into the queue. This means that we need at least two different threads in our unit test. While the one thread blocks, the other thread waits for some specific time. If during this time the other thread does not execute further code, we can assume that the blocking feature is working. One way to check that the blocking thread is not executing any further code is the addition of some boolean flags that are set, when either an exception was thrown or the line after the <code>get()<\/code> call was executed:<\/p>\n<pre class=\"brush:java\">\n\tprivate static class BlockingThread extends Thread {\n\t\tprivate SimpleBlockingQueue queue;\n\t\tprivate boolean wasInterrupted = false;\n\t\tprivate boolean reachedAfterGet = false;\n\t\tprivate boolean throwableThrown;\n\n\t\tpublic BlockingThread(SimpleBlockingQueue queue) {\n\t\t\tthis.queue = queue;\n\t\t}\n\t\t\n\t\tpublic void run() {\n\t\t\ttry {\n\t\t\t\ttry {\n\t\t\t\t\tqueue.get();\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\twasInterrupted = true;\n\t\t\t\t}\n\t\t\t\treachedAfterGet = true;\n\t\t\t} catch (Throwable t) {\n\t\t\t\tthrowableThrown = true;\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean isWasInterrupted() {\n\t\t\treturn wasInterrupted;\n\t\t}\n\n\t\tpublic boolean isReachedAfterGet() {\n\t\t\treturn reachedAfterGet;\n\t\t}\n\t\t\n\t\tpublic boolean isThrowableThrown() {\n\t\t\treturn throwableThrown;\n\t\t}\n\t}\n<\/pre>\n<p>The flag <code>wasInterrupted<\/code> indicates whether the blocking thread was interrupted, the flag <code>reachedAfterGet<\/code> shows that the line after the get has been executed and finally the <code>throwableThrown<\/code> would tell us that any kind of <code>Throwable<\/code> was thrown. With the getter methods for these flags we can now write a unit test, that first creates an empty queue, starts our <code>BlockingThread<\/code>, waits for some time and then inserts a new element into the queue.<\/p>\n<pre class=\"brush:java\">\n\t@Test\n\tpublic void testPutOnEmptyQueueBlocks() throws InterruptedException {\n\t\tfinal SimpleBlockingQueue queue = new SimpleBlockingQueue();\n\t\tBlockingThread blockingThread = new BlockingThread(queue);\n\t\tblockingThread.start();\n\t\tThread.sleep(5000);\n\t\tassertThat(blockingThread.isReachedAfterGet(), is(false));\n\t\tassertThat(blockingThread.isWasInterrupted(), is(false));\n\t\tassertThat(blockingThread.isThrowableThrown(), is(false));\n\t\tqueue.put(new Object());\n\t\tThread.sleep(1000);\n\t\tassertThat(blockingThread.isReachedAfterGet(), is(true));\n\t\tassertThat(blockingThread.isWasInterrupted(), is(false));\n\t\tassertThat(blockingThread.isThrowableThrown(), is(false));\n\t\tblockingThread.join();\n\t}\n<\/pre>\n<p>Before the insertion all flags should be false. If this is the case, we put a new element into the queue and check that the flag <code>reachedAfterGet<\/code> is set to true. All other flags should still be false. Finally we can <code>join()<\/code> the <code>blockingThread<\/code>.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h3><a name=\"test_correctness\"><\/a>2.2. Testing for correctness<\/h3>\n<p>The previous test has just shown how to test a blocking operation. Even more interesting is the real multi-threading test case, where we have more than one thread adding elements to the queue and a bunch of worker threads that retrieve these values from the queue. Basically this means to create a few producer threads that insert new elements into the queue and to setup a bunch of worker threads that call <code>get()<\/code>. <\/p>\n<p>But how do we know that the worker threads have got exactly the same elements from the queue, which the producer threads have inserted before? One possible solution would be to have a second queue where we add and remove the elements based on some unique id (e.g. a UUID). But as we are in a multi-threaded environment, we also have to synchronize access to this second queue and the creation of some unique ID also enforces some kind of synchronization.<\/p>\n<p>A better solution would be some mathematical means that can be implemented without any additional synchronization. The easiest means is here to use integer values as queue elements, which are retrieved from a thread local random generator. The special class <code>ThreadLocalRandom<\/code> manages a random generator for each thread; hence we don&#8217;t have any synchronization overhead. While the producer threads compute the sum over the elements inserted by them, the worker threads also compute their local sum. At the end sum over all producer threads is compared to the sum of all consumer threads. If it is the same, we can assume that with high probability we have retrieved all tasks that have been inserted before.<\/p>\n<p>The following unit test implements these ideas by submitting the consumer and producer threads as tasks to a fixed thread pool:<\/p>\n<pre class=\"brush:java\">\n\t@Test\n\tpublic void testParallelInsertionAndConsumption() throws InterruptedException, ExecutionException {\n\t\tfinal SimpleBlockingQueue&lt;Integer&gt; queue = new SimpleBlockingQueue&lt;Integer&gt;();\n\t\tExecutorService threadPool = Executors.newFixedThreadPool(NUM_THREADS);\n\t\tfinal CountDownLatch latch = new CountDownLatch(NUM_THREADS);\n\t\tList&lt;Future&lt;Integer&gt;&gt; futuresPut = new ArrayList&lt;Future&lt;Integer&gt;&gt;();\n\t\tfor (int i = 0; i &lt; 3; i++) {\n\t\t\tFuture&lt;Integer&gt; submit = threadPool.submit(new Callable&lt;Integer&gt;() {\n\t\t\t\tpublic Integer call() {\n\t\t\t\t\tint sum = 0;\n\t\t\t\t\tfor (int i = 0; i &lt; 1000; i++) {\n\t\t\t\t\t\tint nextInt = ThreadLocalRandom.current().nextInt(100);\n\t\t\t\t\t\tqueue.put(nextInt);\n\t\t\t\t\t\tsum += nextInt;\n\t\t\t\t\t}\n\t\t\t\t\tlatch.countDown();\n\t\t\t\t\treturn sum;\n\t\t\t\t}\n\t\t\t});\n\t\t\tfuturesPut.add(submit);\n\t\t}\n\t\tList&lt;Future&lt;Integer&gt;&gt; futuresGet = new ArrayList&lt;Future&lt;Integer&gt;&gt;();\n\t\tfor (int i = 0; i &lt; 3; i++) {\n\t\t\tFuture&lt;Integer&gt; submit = threadPool.submit(new Callable&lt;Integer&gt;() {\n\t\t\t\tpublic Integer call() {\n\t\t\t\t\tint count = 0;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (int i = 0; i &lt; 1000; i++) {\n\t\t\t\t\t\t\tInteger got = queue.get();\n\t\t\t\t\t\t\tcount += got;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (InterruptedException e) {\n\n\t\t\t\t\t}\n\t\t\t\t\tlatch.countDown();\n\t\t\t\t\treturn count;\n\t\t\t\t}\n\t\t\t});\n\t\t\tfuturesGet.add(submit);\n\t\t}\n\t\tlatch.await();\n\t\tint sumPut = 0;\n\t\tfor (Future&lt;Integer&gt; future : futuresPut) {\n\t\t\tsumPut += future.get();\n\t\t}\n\t\tint sumGet = 0;\n\t\tfor (Future&lt;Integer&gt; future : futuresGet) {\n\t\t\tsumGet += future.get();\n\t\t}\n\t\tassertThat(sumPut, is(sumGet));\n\t}\n<\/pre>\n<p>We use a <code>CountDownLatch<\/code> in order to wait until all threads have finished. Finally we can compute the sum over all submitted and retrieved integers and assert that both are equal.<\/p>\n<p>The order in which the different threads are executed is hard to predict. It depends on many dynamic factors like interrupts handled by the operating system and how the scheduler chooses the next thread to execute. In order to achieve more context switches, one can call the method <code>Thread.yield()<\/code>. This gives the scheduler a hint that the current thread is willing to yield the CPU in favor of another thread. As the javadoc states, this is only a hint, i.e. the JVM can completely ignore this hint and execute the current thread further. But for testing purposes one may use this method to introduce more context switches and therefore provoke race conditions, etc.<br \/>\n[ulp id=&#8217;DdINgEqoOovgkhhk-3&#8242;]<br \/>\n&nbsp;<\/p>\n<h3><a name=\"test_perf\"><\/a>2.3. Testing performance<\/h3>\n<p>Another aspect next to the correct behavior of a class is its performance. In many real world applications performance is an important requirement and therefore has to be tested.<\/p>\n<p>We can utilize an <code>ExecutorService<\/code> to setup a varying number of threads. Each thread is supposed to insert an element into our queue and take it afterwards from it. Within an outer loop we increment the number of threads in order to see how the number of threads impacts the throughput.<\/p>\n<pre class=\"brush:java\">\n\t@Test\n\tpublic void testPerformance() throws InterruptedException {\n\t\tfor (int numThreads = 1; numThreads &lt; THREADS_MAX; numThreads++) {\n\t\t\tlong startMillis = System.currentTimeMillis();\n\t\t\tfinal SimpleBlockingQueue&lt;Integer&gt; queue = new SimpleBlockingQueue&lt;Integer&gt;();\n\t\t\tExecutorService threadPool = Executors.newFixedThreadPool(numThreads);\n\t\t\tfor (int i = 0; i &lt; numThreads; i++) {\n\t\t\t\tthreadPool.submit(new Runnable() {\n\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\tfor (long i = 0; i &lt; ITERATIONS; i++) {\n\t\t\t\t\t\t\tint nextInt = ThreadLocalRandom.current().nextInt(100);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tqueue.put(nextInt);\n\t\t\t\t\t\t\t\tnextInt = queue.get();\n\t\t\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\t\t\te.printStackTrace();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tthreadPool.shutdown();\n\t\t\tthreadPool.awaitTermination(5, TimeUnit.MINUTES);\n\t\t\tlong totalMillis = System.currentTimeMillis() - startMillis;\n\t\t\tdouble throughput = (double)(numThreads * ITERATIONS * 2) \/ (double) totalMillis;\n\t\t\tSystem.out.println(String.format(\"%s with %d threads: %dms (throughput: %.1f ops\/s)\", LinkedBlockingQueue.class.getSimpleName(), numThreads, totalMillis, throughput));\n\t\t}\n\t}\n<\/pre>\n<p>To get a feeling on how our simple queue implementation performs, we can compare it to an implementation from the JDK. A candidate for this is the <code>LinkedBlockingQueue<\/code>. Its two methods <code>put()<\/code> and <code>take()<\/code> work similar to our implementation, expect the circumstance that <code>LinkedBlockingQueue<\/code> is optionally bounded and therefore has to keep track of the number of inserted elements and lets the current thread sleep if the queue is full. This functionality needs additional bookkeeping and checking on insert operations. On the other hand the JDK implementation does not use synchronized blocks and has been implemented with tedious performance measurements.<\/p>\n<p>When we implement the same test case as above using the <code>LinkedBlockingQueue<\/code>, we get the following output for both test cases:<\/p>\n<p><figure id=\"attachment_4498\" aria-describedby=\"caption-attachment-4498\" style=\"width: 619px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/Figure-1.png\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/Figure-1.png\" alt=\"Figure 1\" width=\"619\" height=\"386\" class=\"size-full wp-image-4498\" \/><\/a><figcaption id=\"caption-attachment-4498\" class=\"wp-caption-text\">Figure 1<\/figcaption><\/figure><\/p>\n<p>The figure clearly shows that the throughput rate, i.e. the number of operations performed per time unit, is nearly twice as good for the <code>LinkedBlockingQueue<\/code> implementation. But it also shows that with only one thread both implementations make about the same number of operations per second. Adding more threads improves the throughput, although the curve converges very soon against its saturation value. Adding more threads does not improve the performance of the application any more.<\/p>\n<h2><a name=\"frameworks\"><\/a>3. Testing frameworks<\/h2>\n<p>Instead of writing your own framework for implementing multi-threaded test cases for your application, you can have look at the available test framework. This section puts a light on two of them: JMock and Grobo Utils.<\/p>\n<h3><a name=\"jmock\"><\/a>3.1. JMock<\/h3>\n<p>For stress testing purposes the mocking framework JMock provides the class Blitzer. This class implements functionality similar to what we have done in section &#8220;Testing for correctness&#8221; as it internally set ups a <code>ThreadPool<\/code> to which tasks are submitted that execute some specific action. You provide the number of tasks\/actions to perform as well as the number of threads to the constructor:<\/p>\n<pre class=\"brush:java\">\nBlitzer blitzer = new Blitzer(25000, 6);\n<\/pre>\n<p>This instance has a method <code>blitz()<\/code> to which you just provide an implementation of the <code>Runnable<\/code> interface:<\/p>\n<pre class=\"brush:java\">\n\t@Test\n\tpublic void stressTest() throws InterruptedException {\n\t\tfinal SimpleBlockingQueue&lt;Integer&gt; queue = new SimpleBlockingQueue&lt;Integer&gt;();\n\t\tblitzer.blitz(new Runnable() {\n\t\t\tpublic void run() {\n\t\t\t\ttry {\n\t\t\t\t\tqueue.put(42);\n\t\t\t\t\tqueue.get();\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tassertThat(queue.getSize(), is(0));\n\t}\n<\/pre>\n<p>The <code>Blitzer<\/code> class therefore makes the implementation of stress tests even simpler than it is with an <code>ExecutorService<\/code>.<\/p>\n<h3><a name=\"groboutils\"><\/a>3.2. Grobo Utils<\/h3>\n<p><a href=\"http:\/\/groboutils.sourceforge.net\/index.html\">Grobo Utils<\/a> is a framework providing support for testing multi-threaded applications. The ideas behind the framework are described in <a href=\"http:\/\/www.javaworld.com\/article\/2076265\/testing-debugging\/junit-best-practices.html\">article<\/a>.<\/p>\n<p>Similar to the previous example we have the class <code>MultiThreadedTestRunner<\/code> that internally constructs a thread pool and executes a given number of Runnable implementations as separate threads. The <code>Runnable<\/code> instances have to implement a special interface called <code>TestRunnable<\/code>. It is worth mentioning that its only method <code>runTest()<\/code> throws an exception. This way, exceptions thrown within the threads have an influence on the test result. This is not the case when we use a normal <code>ExecutorService<\/code>. Here the tasks have to implement <code>Runnable<\/code> and its only method <code>run()<\/code> does not throw any exception. Exceptions thrown within these tasks are swallowed and don&#8217;t break the test.<\/p>\n<p>After having constructed the <code>MultiThreadedTestRunner<\/code> we can call its <code>runTestRunnables()<\/code> method and provide the number of milliseconds it should wait until the test should fail. Finally the <code>assertThat()<\/code> call verifies that the queue is empty again, as all test threads have removed the previously added element.<\/p>\n<pre class=\"brush:java\">\npublic class SimpleBlockingQueueGroboUtilTest {\n\n\tprivate static class MyTestRunnable extends TestRunnable {\n\t\tprivate SimpleBlockingQueue&lt;Integer&gt; queue;\n\n\t\tpublic MyTestRunnable(SimpleBlockingQueue&lt;Integer&gt; queue) {\n\t\t\tthis.queue = queue;\n\t\t}\n\n\t\t@Override\n\t\tpublic void runTest() throws Throwable {\n\t\t\tfor (int i = 0; i &lt; 1000000; i++) {\n\t\t\t\tthis.queue.put(42);\n\t\t\t\tthis.queue.get();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tpublic void stressTest() throws Throwable {\n\t\tSimpleBlockingQueue&lt;Integer&gt; queue = new SimpleBlockingQueue&lt;Integer&gt;();\n\t\tTestRunnable[] testRunnables = new TestRunnable[6];\n\t\tfor (int i = 0; i &lt; testRunnables.length; i++) {\n\t\t\ttestRunnables[i] = new MyTestRunnable(queue);\n\t\t}\n\t\tMultiThreadedTestRunner mttr = new MultiThreadedTestRunner(testRunnables);\n\t\tmttr.runTestRunnables(2 * 60 * 1000);\n\t\tassertThat(queue.getSize(), is(0));\n\t}\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be introduced to the fundamentals of concurrency and concurrent code and you will learn about concepts like atomicity, synchronization and thread safety. Check it out here! Table Of Contents 1. &hellip;<\/p>\n","protected":false},"author":506,"featured_media":148,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[88,121,380],"class_list":["post-43750","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-java","tag-concurrency","tag-performance-and-scalability","tag-threads"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Testing Concurrent Applications - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Testing Concurrent Applications - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-16T16:36:45+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-13T09:52:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Martin Mois\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Martin Mois\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html\"},\"author\":{\"name\":\"Martin Mois\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/52c1e27ea19337c20d53df5286590760\"},\"headline\":\"Testing Concurrent Applications\",\"datePublished\":\"2015-09-16T16:36:45+00:00\",\"dateModified\":\"2023-12-13T09:52:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html\"},\"wordCount\":1534,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"keywords\":[\"Concurrency\",\"Performance and Scalability\",\"Threads\"],\"articleSection\":[\"Core Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html\",\"name\":\"Testing Concurrent Applications - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"datePublished\":\"2015-09-16T16:36:45+00:00\",\"dateModified\":\"2023-12-13T09:52:50+00:00\",\"description\":\"This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/testing-concurrent-applications.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Core Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/core-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Testing Concurrent Applications\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/52c1e27ea19337c20d53df5286590760\",\"name\":\"Martin Mois\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/051a80ba18f758940b686c6c4bb4b5f02d59abe8cc42a95b3545f7565c7a40a1?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/051a80ba18f758940b686c6c4bb4b5f02d59abe8cc42a95b3545f7565c7a40a1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/051a80ba18f758940b686c6c4bb4b5f02d59abe8cc42a95b3545f7565c7a40a1?s=96&d=mm&r=g\",\"caption\":\"Martin Mois\"},\"description\":\"Martin is a Java EE enthusiast and works for an international operating company. He is interested in clean code and the software craftsmanship approach. He also strongly believes in automated testing and continuous integration.\",\"sameAs\":[\"http:\\\/\\\/martinsdeveloperworld.wordpress.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/martin-mois\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Testing Concurrent Applications - Java Code Geeks","description":"This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html","og_locale":"en_US","og_type":"article","og_title":"Testing Concurrent Applications - Java Code Geeks","og_description":"This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be","og_url":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-09-16T16:36:45+00:00","article_modified_time":"2023-12-13T09:52:50+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","type":"image\/jpeg"}],"author":"Martin Mois","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Martin Mois","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html"},"author":{"name":"Martin Mois","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/52c1e27ea19337c20d53df5286590760"},"headline":"Testing Concurrent Applications","datePublished":"2015-09-16T16:36:45+00:00","dateModified":"2023-12-13T09:52:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html"},"wordCount":1534,"commentCount":4,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","keywords":["Concurrency","Performance and Scalability","Threads"],"articleSection":["Core Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html","url":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html","name":"Testing Concurrent Applications - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","datePublished":"2015-09-16T16:36:45+00:00","dateModified":"2023-12-13T09:52:50+00:00","description":"This article is part of our Academy Course titled Java Concurrency Essentials. In this course, you will dive into the magic of concurrency. You will be","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/testing-concurrent-applications.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Core Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/core-java"},{"@type":"ListItem","position":4,"name":"Testing Concurrent Applications"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/52c1e27ea19337c20d53df5286590760","name":"Martin Mois","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/051a80ba18f758940b686c6c4bb4b5f02d59abe8cc42a95b3545f7565c7a40a1?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/051a80ba18f758940b686c6c4bb4b5f02d59abe8cc42a95b3545f7565c7a40a1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/051a80ba18f758940b686c6c4bb4b5f02d59abe8cc42a95b3545f7565c7a40a1?s=96&d=mm&r=g","caption":"Martin Mois"},"description":"Martin is a Java EE enthusiast and works for an international operating company. He is interested in clean code and the software craftsmanship approach. He also strongly believes in automated testing and continuous integration.","sameAs":["http:\/\/martinsdeveloperworld.wordpress.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/martin-mois"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/43750","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/506"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=43750"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/43750\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/148"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=43750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=43750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=43750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}