What is thread-safety and how to achieve it
Issue: BAEL-2416
This commit is contained in:
		
							parent
							
								
									65b9909fed
								
							
						
					
					
						commit
						04743892db
					
				| @ -0,0 +1,86 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.application; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.AtomicCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.mathutils.MathUtils; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.CounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.AtomicCounter; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.Counter; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.MessageService; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.concurrent.ConcurrentHashMap; | ||||||
|  | import java.util.concurrent.ExecutionException; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.Future; | ||||||
|  | 
 | ||||||
|  | public class Application { | ||||||
|  |      | ||||||
|  |     public static void main(String[] args) throws InterruptedException, ExecutionException { | ||||||
|  | 
 | ||||||
|  |         new Thread(() -> { | ||||||
|  |             System.out.println(MathUtils.factorial(10)); | ||||||
|  |         }).start(); | ||||||
|  |         new Thread(() -> { | ||||||
|  |             System.out.println(MathUtils.factorial(5)); | ||||||
|  |         }).start(); | ||||||
|  |          | ||||||
|  |         ExecutorService executorService = Executors.newFixedThreadPool(10); | ||||||
|  |         MessageService messageService = new MessageService("Welcome to Baeldung!"); | ||||||
|  |         Future<String> future1 = (Future<String>) executorService.submit(new MessageServiceCallable(messageService)); | ||||||
|  |         Future<String> future2 = (Future<String>) executorService.submit(new MessageServiceCallable(messageService)); | ||||||
|  |         System.out.println(future1.get()); | ||||||
|  |         System.out.println(future2.get()); | ||||||
|  |          | ||||||
|  |         Counter counter = new Counter(); | ||||||
|  |         Future<Integer> future3 = (Future<Integer>) executorService.submit(new CounterCallable(counter)); | ||||||
|  |         Future<Integer> future4 = (Future<Integer>) executorService.submit(new CounterCallable(counter)); | ||||||
|  |         System.out.println(future3.get()); | ||||||
|  |         System.out.println(future4.get()); | ||||||
|  |          | ||||||
|  |         ExtrinsicLockCounter extrinsicLockCounter = new ExtrinsicLockCounter(); | ||||||
|  |         Future<Integer> future5 = (Future<Integer>) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter)); | ||||||
|  |         Future<Integer> future6 = (Future<Integer>) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter)); | ||||||
|  |         System.out.println(future5.get()); | ||||||
|  |         System.out.println(future6.get()); | ||||||
|  |          | ||||||
|  |         ReentrantLockCounter reentrantLockCounter = new ReentrantLockCounter(); | ||||||
|  |         Future<Integer> future7 = (Future<Integer>) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter)); | ||||||
|  |         Future<Integer> future8 = (Future<Integer>) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter)); | ||||||
|  |         System.out.println(future7.get()); | ||||||
|  |         System.out.println(future8.get()); | ||||||
|  |          | ||||||
|  |         ReentrantReadWriteLockCounter reentrantReadWriteLockCounter = new ReentrantReadWriteLockCounter(); | ||||||
|  |         Future<Integer> future9 = (Future<Integer>) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter)); | ||||||
|  |         Future<Integer> future10 = (Future<Integer>) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter)); | ||||||
|  |         System.out.println(future9.get()); | ||||||
|  |         System.out.println(future10.get()); | ||||||
|  |          | ||||||
|  |         AtomicCounter atomicCounter = new AtomicCounter(); | ||||||
|  |         Future<Integer> future11 = (Future<Integer>) executorService.submit(new AtomicCounterCallable(atomicCounter)); | ||||||
|  |         Future<Integer> future12 = (Future<Integer>) executorService.submit(new AtomicCounterCallable(atomicCounter)); | ||||||
|  |         System.out.println(future11.get()); | ||||||
|  |         System.out.println(future12.get()); | ||||||
|  |          | ||||||
|  |         Collection<Integer> syncCollection = Collections.synchronizedCollection(new ArrayList<>()); | ||||||
|  |         Thread thread11 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6))); | ||||||
|  |         Thread thread12 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6))); | ||||||
|  |         thread11.start(); | ||||||
|  |         thread12.start(); | ||||||
|  |          | ||||||
|  |         Map<String,String> concurrentMap = new ConcurrentHashMap<>(); | ||||||
|  |         concurrentMap.put("1", "one"); | ||||||
|  |         concurrentMap.put("2", "two"); | ||||||
|  |         concurrentMap.put("3", "three"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.callables; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.AtomicCounter; | ||||||
|  | import java.util.concurrent.Callable; | ||||||
|  | 
 | ||||||
|  | public class AtomicCounterCallable implements Callable<Integer> { | ||||||
|  | 
 | ||||||
|  |     private final AtomicCounter counter; | ||||||
|  |      | ||||||
|  |     public AtomicCounterCallable(AtomicCounter counter) { | ||||||
|  |         this.counter = counter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Integer call() throws Exception { | ||||||
|  |         counter.incrementCounter(); | ||||||
|  |         return counter.getCounter(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.callables; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.Counter; | ||||||
|  | import java.util.concurrent.Callable; | ||||||
|  | 
 | ||||||
|  | public class CounterCallable implements Callable<Integer> { | ||||||
|  | 
 | ||||||
|  |     private final Counter counter; | ||||||
|  |      | ||||||
|  |     public CounterCallable(Counter counter) { | ||||||
|  |         this.counter = counter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Integer call() throws Exception { | ||||||
|  |         counter.incrementCounter(); | ||||||
|  |         return counter.getCounter(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.callables; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; | ||||||
|  | import java.util.concurrent.Callable; | ||||||
|  | 
 | ||||||
|  | public class ExtrinsicLockCounterCallable implements Callable<Integer> { | ||||||
|  | 
 | ||||||
|  |     private final ExtrinsicLockCounter counter; | ||||||
|  |      | ||||||
|  |     public ExtrinsicLockCounterCallable(ExtrinsicLockCounter counter) { | ||||||
|  |         this.counter = counter; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Override | ||||||
|  |     public Integer call() throws Exception { | ||||||
|  |         counter.incrementCounter(); | ||||||
|  |         return counter.getCounter(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.callables; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.MessageService; | ||||||
|  | import java.util.concurrent.Callable; | ||||||
|  | 
 | ||||||
|  | public class MessageServiceCallable implements Callable<String> { | ||||||
|  |      | ||||||
|  |     private final MessageService messageService; | ||||||
|  |      | ||||||
|  |     public MessageServiceCallable(MessageService messageService) { | ||||||
|  |         this.messageService = messageService; | ||||||
|  |      | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Override | ||||||
|  |     public String call() { | ||||||
|  |         return messageService.getMesssage(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.callables; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; | ||||||
|  | import java.util.concurrent.Callable; | ||||||
|  | 
 | ||||||
|  | public class ReentranReadWriteLockCounterCallable implements Callable<Integer> { | ||||||
|  | 
 | ||||||
|  |     private final ReentrantReadWriteLockCounter counter; | ||||||
|  | 
 | ||||||
|  |     public ReentranReadWriteLockCounterCallable(ReentrantReadWriteLockCounter counter) { | ||||||
|  |         this.counter = counter; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Override | ||||||
|  |     public Integer call() throws Exception { | ||||||
|  |         counter.incrementCounter(); | ||||||
|  |         return counter.getCounter(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.callables; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; | ||||||
|  | import java.util.concurrent.Callable; | ||||||
|  | 
 | ||||||
|  | public class ReentrantLockCounterCallable implements Callable<Integer> { | ||||||
|  | 
 | ||||||
|  |     private final ReentrantLockCounter counter; | ||||||
|  |      | ||||||
|  |     public ReentrantLockCounterCallable(ReentrantLockCounter counter) { | ||||||
|  |         this.counter = counter; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Override | ||||||
|  |     public Integer call() throws Exception { | ||||||
|  |         counter.incrementCounter(); | ||||||
|  |         return counter.getCounter(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.mathutils; | ||||||
|  | 
 | ||||||
|  | import java.math.BigInteger; | ||||||
|  | 
 | ||||||
|  | public class MathUtils { | ||||||
|  |      | ||||||
|  |     public static BigInteger factorial(int number) { | ||||||
|  |         BigInteger f = new BigInteger("1"); | ||||||
|  |         for (int i = 2; i <= number; i++) { | ||||||
|  |             f = f.multiply(BigInteger.valueOf(i)); | ||||||
|  |         } | ||||||
|  |         return f; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,18 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.atomic.AtomicInteger; | ||||||
|  | 
 | ||||||
|  | public class AtomicCounter { | ||||||
|  |      | ||||||
|  |     private final AtomicInteger counter = new AtomicInteger(); | ||||||
|  |      | ||||||
|  |     public AtomicCounter() {} | ||||||
|  |      | ||||||
|  |     public void incrementCounter() { | ||||||
|  |         counter.incrementAndGet(); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public synchronized int getCounter() { | ||||||
|  |         return counter.get(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,18 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | public class Counter { | ||||||
|  |      | ||||||
|  |     private volatile int counter; | ||||||
|  |      | ||||||
|  |     public Counter() { | ||||||
|  |         this.counter = 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public synchronized void incrementCounter() { | ||||||
|  |         counter += 1; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public int getCounter() { | ||||||
|  |         return counter; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | public class ExtrinsicLockCounter { | ||||||
|  | 
 | ||||||
|  |     private int counter; | ||||||
|  |     private final Object lock = new Object(); | ||||||
|  | 
 | ||||||
|  |     public ExtrinsicLockCounter() { | ||||||
|  |         this.counter = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void incrementCounter() { | ||||||
|  |         synchronized (lock) { | ||||||
|  |             counter += 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getCounter() { | ||||||
|  |         synchronized (lock) { | ||||||
|  |             return counter; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | public class MessageService { | ||||||
|  |      | ||||||
|  |     private final String message; | ||||||
|  |      | ||||||
|  |     public MessageService(String message) { | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public String getMesssage() { | ||||||
|  |         return message; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.locks.ReentrantLock; | ||||||
|  | 
 | ||||||
|  | public class ReentrantLockCounter { | ||||||
|  | 
 | ||||||
|  |     private int counter; | ||||||
|  |     private final ReentrantLock reLock = new ReentrantLock(true); | ||||||
|  | 
 | ||||||
|  |     public ReentrantLockCounter() { | ||||||
|  |         this.counter = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void incrementCounter() { | ||||||
|  |         reLock.lock(); | ||||||
|  |         try { | ||||||
|  |             counter += 1; | ||||||
|  |         } finally { | ||||||
|  |             reLock.unlock(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getCounter() { | ||||||
|  |         return counter; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | import java.util.concurrent.locks.Lock; | ||||||
|  | import java.util.concurrent.locks.ReentrantReadWriteLock; | ||||||
|  | 
 | ||||||
|  | public class ReentrantReadWriteLockCounter { | ||||||
|  |      | ||||||
|  |     private int counter; | ||||||
|  |     private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); | ||||||
|  |     private final Lock readLock = rwLock.readLock(); | ||||||
|  |     private final Lock writeLock = rwLock.writeLock(); | ||||||
|  |      | ||||||
|  |     public ReentrantReadWriteLockCounter() { | ||||||
|  |         this.counter = 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public void incrementCounter() { | ||||||
|  |         writeLock.lock(); | ||||||
|  |         try { | ||||||
|  |             counter += 1; | ||||||
|  |         } finally { | ||||||
|  |             writeLock.unlock(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public int getCounter() { | ||||||
|  |         readLock.lock(); | ||||||
|  |         try { | ||||||
|  |             return counter; | ||||||
|  |         } finally { | ||||||
|  |             readLock.unlock(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.services; | ||||||
|  | 
 | ||||||
|  | public class StateHolder { | ||||||
|  |      | ||||||
|  |     private final String state; | ||||||
|  | 
 | ||||||
|  |     public StateHolder(String state) { | ||||||
|  |         this.state = state; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public String getState() { | ||||||
|  |         return state; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.tests; | ||||||
|  | 
 | ||||||
|  | import org.junit.Test; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.CounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.Counter; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.Future; | ||||||
|  | 
 | ||||||
|  | public class CounterTest { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void whenCalledIncrementCounter_thenCorrect() throws Exception { | ||||||
|  |         ExecutorService executorService = Executors.newFixedThreadPool(2); | ||||||
|  |         Counter counter = new Counter(); | ||||||
|  |         Future<Integer> future1 = (Future<Integer>) executorService.submit(new CounterCallable(counter)); | ||||||
|  |         Future<Integer> future2 = (Future<Integer>) executorService.submit(new CounterCallable(counter)); | ||||||
|  |          | ||||||
|  |         assertThat(future1.get()).isEqualTo(1); | ||||||
|  |         assertThat(future2.get()).isEqualTo(2); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.tests; | ||||||
|  | 
 | ||||||
|  | import org.junit.Test; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.Future; | ||||||
|  | 
 | ||||||
|  | public class ExtrinsicLockCounterTest { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void whenCalledIncrementCounter_thenCorrect() throws Exception { | ||||||
|  |         ExecutorService executorService = Executors.newFixedThreadPool(2); | ||||||
|  |         ExtrinsicLockCounter counter = new ExtrinsicLockCounter(); | ||||||
|  |         Future<Integer> future1 = (Future<Integer>) executorService.submit(new ExtrinsicLockCounterCallable(counter)); | ||||||
|  |         Future<Integer> future2 = (Future<Integer>) executorService.submit(new ExtrinsicLockCounterCallable(counter)); | ||||||
|  |          | ||||||
|  |         assertThat(future1.get()).isEqualTo(1); | ||||||
|  |         assertThat(future2.get()).isEqualTo(2); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,13 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.tests; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.mathutils.MathUtils; | ||||||
|  | import org.junit.Test; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | 
 | ||||||
|  | public class MathUtilsTest { | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void whenCalledFactorialMethod_thenCorrect() { | ||||||
|  |         assertThat(MathUtils.factorial(2)).isEqualTo(2); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.tests; | ||||||
|  | 
 | ||||||
|  | import org.junit.Test; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.MessageService; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.Future; | ||||||
|  | 
 | ||||||
|  | public class MessageServiceTest { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void whenCalledgetMessage_thenCorrect() throws Exception { | ||||||
|  |         ExecutorService executorService = Executors.newFixedThreadPool(2); | ||||||
|  |         MessageService messageService = new MessageService("Welcome to Baeldung!"); | ||||||
|  |         Future<String> future1 = (Future<String>) executorService.submit(new MessageServiceCallable(messageService)); | ||||||
|  |         Future<String> future2 = (Future<String>) executorService.submit(new MessageServiceCallable(messageService)); | ||||||
|  | 
 | ||||||
|  |         assertThat(future1.get()).isEqualTo("Welcome to Baeldung!"); | ||||||
|  |         assertThat(future2.get()).isEqualTo("Welcome to Baeldung!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.tests; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.Future; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | public class ReentrantLockCounterTest { | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void whenCalledIncrementCounter_thenCorrect() throws Exception { | ||||||
|  |         ExecutorService executorService = Executors.newFixedThreadPool(2); | ||||||
|  |         ReentrantLockCounter counter = new ReentrantLockCounter(); | ||||||
|  |         Future<Integer> future1 = (Future<Integer>) executorService.submit(new ReentrantLockCounterCallable(counter)); | ||||||
|  |         Future<Integer> future2 = (Future<Integer>) executorService.submit(new ReentrantLockCounterCallable(counter)); | ||||||
|  |          | ||||||
|  |         assertThat(future1.get()).isEqualTo(1); | ||||||
|  |         assertThat(future2.get()).isEqualTo(2); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  | package com.baeldung.concurrent.threadsafety.tests; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable; | ||||||
|  | import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; | ||||||
|  | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
|  | import java.util.concurrent.Future; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | public class ReentrantReadWriteLockCounterTest { | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void whenCalledIncrementCounter_thenCorrect() throws Exception { | ||||||
|  |         ExecutorService executorService = Executors.newFixedThreadPool(2); | ||||||
|  |         ReentrantReadWriteLockCounter counter = new ReentrantReadWriteLockCounter(); | ||||||
|  |         Future<Integer> future1 = (Future<Integer>) executorService.submit(new  ReentranReadWriteLockCounterCallable(counter)); | ||||||
|  |         Future<Integer> future2 = (Future<Integer>) executorService.submit(new  ReentranReadWriteLockCounterCallable(counter)); | ||||||
|  |          | ||||||
|  |         assertThat(future1.get()).isEqualTo(1); | ||||||
|  |         assertThat(future2.get()).isEqualTo(2); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user