BAEL-1029 - deep20jain@gmail.com - An Introduction to Atomic Variables in Java (#2269)
* Adding test classes for java atomic variables * Updating counter with atomic integer * Adding reason for ignoring test
This commit is contained in:
parent
2ce547d4cd
commit
afa82c0d28
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
public class SafeCounterWithLock {
|
||||
int counter;
|
||||
|
||||
public int getValue() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public synchronized void increment() {
|
||||
counter++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SafeCounterWithoutLock {
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
public int getValue() {
|
||||
return counter.get();
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
while(true) {
|
||||
int existingValue = getValue();
|
||||
int newValue = existingValue + 1;
|
||||
if(counter.compareAndSet(existingValue, newValue)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
public class UnsafeCounter {
|
||||
int counter;
|
||||
|
||||
public int getValue() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
counter++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CounterTest {
|
||||
|
||||
/**
|
||||
* This test shows the behaviour of a thread-unsafe class in a multithreaded scenario. We are calling
|
||||
* the increment methods 1000 times from a pool of 3 threads. In most of the cases, the counter will
|
||||
* less than 1000, because of lost updates, however, occasionally it may reach 1000, when no threads
|
||||
* called the method simultaneously. This may cause the build to fail occasionally. Hence excluding this
|
||||
* test by adding Ignore annotation.
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void givenMultiThread_whenUnsafeCounterIncrement() throws InterruptedException {
|
||||
ExecutorService service = Executors.newFixedThreadPool(3);
|
||||
UnsafeCounter unsafeCounter = new UnsafeCounter();
|
||||
|
||||
IntStream.range(0, 1000)
|
||||
.forEach(count -> service.submit(unsafeCounter::increment));
|
||||
service.awaitTermination(100, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertEquals(1000, unsafeCounter.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultiThread_whenSafeCounterWithLockIncrement() throws InterruptedException {
|
||||
ExecutorService service = Executors.newFixedThreadPool(3);
|
||||
SafeCounterWithLock safeCounter = new SafeCounterWithLock();
|
||||
|
||||
IntStream.range(0, 1000)
|
||||
.forEach(count -> service.submit(safeCounter::increment));
|
||||
service.awaitTermination(100, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertEquals(1000, safeCounter.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultiThread_whenSafeCounterWithoutLockIncrement() throws InterruptedException {
|
||||
ExecutorService service = Executors.newFixedThreadPool(3);
|
||||
SafeCounterWithoutLock safeCounter = new SafeCounterWithoutLock();
|
||||
|
||||
IntStream.range(0, 1000)
|
||||
.forEach(count -> service.submit(safeCounter::increment));
|
||||
service.awaitTermination(100, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertEquals(1000, safeCounter.getValue());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue