2323import java .util .concurrent .CountDownLatch ;
2424import java .util .concurrent .ExecutorService ;
2525import java .util .concurrent .Executors ;
26+ import java .util .concurrent .ExecutionException ;
27+ import java .util .concurrent .Future ;
2628import java .util .concurrent .TimeUnit ;
29+ import java .util .concurrent .TimeoutException ;
2730import java .util .concurrent .atomic .AtomicBoolean ;
2831
2932import static org .junit .jupiter .api .Assertions .assertNotNull ;
@@ -53,10 +56,11 @@ void testConcurrentGetContentsAndModification() throws InterruptedException {
5356 final ExecutorService executor = Executors .newFixedThreadPool (numberOfThreads );
5457 final CountDownLatch latch = new CountDownLatch (numberOfThreads );
5558 final AtomicBoolean exceptionOccurred = new AtomicBoolean (false );
59+ final List <Future <?>> tasks = new java .util .ArrayList <>(numberOfThreads );
5660 // Start threads that modify the node while others read from it
5761 for (int i = 0 ; i < numberOfThreads ; i ++) {
5862 final int threadId = i ;
59- executor .submit (() -> {
63+ tasks . add ( executor .submit (() -> {
6064 try {
6165 for (int j = 0 ; j < numberOfOperations ; j ++) {
6266 if (threadId % 2 == 0 ) {
@@ -69,7 +73,7 @@ void testConcurrentGetContentsAndModification() throws InterruptedException {
6973 assertNotNull (lsaSpace );
7074 } else {
7175 // Writer threads
72- final ILsaMolecule newMolecule = new LsaMolecule ("thread" + threadId + "_ " + j );
76+ final ILsaMolecule newMolecule = new LsaMolecule ("thread" + threadId + "x " + j );
7377 node .setConcentration (newMolecule );
7478 // Sometimes remove molecules to simulate real concurrent modification
7579 if (j % 10 == 0 && node .getMoleculeCount () > MIN_MOLECULES ) {
@@ -81,17 +85,25 @@ void testConcurrentGetContentsAndModification() throws InterruptedException {
8185 }
8286 }
8387 }
84- } catch (final IllegalStateException | java .util .ConcurrentModificationException e ) {
85- exceptionOccurred .set (true );
86- e .printStackTrace ();
8788 } finally {
8889 latch .countDown ();
8990 }
90- });
91+ return null ;
92+ }));
9193 }
9294 // Wait for all threads to complete
9395 assertTrue (latch .await (TIMEOUT_SECONDS , TimeUnit .SECONDS ), "Test should complete within 30 seconds" );
9496 executor .shutdown ();
97+ for (final Future <?> task : tasks ) {
98+ try {
99+ task .get (TIMEOUT_SECONDS , TimeUnit .SECONDS );
100+ } catch (final InterruptedException e ) {
101+ Thread .currentThread ().interrupt ();
102+ exceptionOccurred .set (true );
103+ } catch (final ExecutionException | TimeoutException e ) {
104+ exceptionOccurred .set (true );
105+ }
106+ }
95107 // No exceptions should have occurred (especially no ConcurrentModificationException)
96108 assertFalse (exceptionOccurred .get (), "No exceptions should occur during concurrent access" );
97109 // Verify the node is still in a valid state
0 commit comments