Backend Development 9 min read

Concurrent Unit Testing of AssetService.update with Optimization Techniques

This article explains how to write a concurrent unit test for the AssetService.update method using thread pools, CountDownLatch, AtomicInteger, and then suggests optimizations such as replacing AtomicInteger with LongAdder and employing CyclicBarrier to increase contention, providing full code examples and detailed explanations.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Concurrent Unit Testing of AssetService.update with Optimization Techniques

Last week the author created a unit test to verify the behavior of @Service public class AssetServiceImpl implements AssetService { @Autowired private TransactionTemplate transactionTemplate; @Override public String update(Asset asset) { // parameter checks, idempotency, fetch latest asset ... return transactionTemplate.execute(status -> { updateAsset(asset); return insertAssetStream(asset); }); } which updates an Asset and inserts an AssetStream, using optimistic locking and a unique constraint to handle concurrency, all wrapped in a local transaction.

The test aims to simulate a high‑concurrency scenario, so it builds a custom thread pool with Guava's ThreadFactoryBuilder , a CountDownLatch to wait for all worker threads, and an AtomicInteger to count failed updates:

public class AssetServiceImplTest { private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build(); private static ExecutorService pool = new ThreadPoolExecutor(20, 100, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue
(128), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); @Autowired private AssetService assetService; @Test public void test_updateConcurrent() { Asset asset = getAsset(); CountDownLatch countDownLatch = new CountDownLatch(10); AtomicInteger failedCount = new AtomicInteger(); for (int i = 0; i < 10; i++) { pool.execute(() -> { try { String streamNo = assetService.update(asset); } catch (Exception e) { System.out.println("Error : " + e); failedCount.incrementAndGet(); } finally { countDownLatch.countDown(); } }); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } Assert.assertEquals(failedCount.intValue(), 9); }

The article then breaks down the key concepts demonstrated by the test: creating a thread pool to avoid OOM, using CountDownLatch for main‑thread synchronization, employing AtomicInteger for thread‑safe failure counting, handling exceptions with try‑catch‑finally, and asserting results with JUnit's Assert .

For further optimization, the author suggests replacing AtomicInteger with LongAdder (a Java 8 class that performs better under high contention) and increasing true parallel execution by adding a CyclicBarrier so that all worker threads start the update simultaneously. The improved test code looks like this:

// main thread latch CountDownLatch mainThreadHolder = new CountDownLatch(10); // barrier for workers CyclicBarrier cyclicBarrier = new CyclicBarrier(10); LongAdder failedCount = new LongAdder(); for (int i = 0; i < 10; i++) { pool.execute(() -> { try { cyclicBarrier.await(); String streamNo = assetService.update(asset); } catch (Exception e) { System.out.println("Error : " + e); failedCount.increment(); } finally { mainThreadHolder.countDown(); } }); } try { mainThreadHolder.await(); } catch (InterruptedException e) { e.printStackTrace(); } Assert.assertEquals(failedCount.intValue(), 9);

Finally, the author invites readers to provide additional optimization ideas and links to related articles on high‑concurrency service tuning, database connection pools, and Redis cache design.

Javaconcurrencythreadpoolunit testingLongAdderCyclicBarrierAtomicInteger
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.