Skip to content

Commit 0474389

Browse files
alejandrogervasiojzheaux
authored andcommitted
What is thread-safety and how to achieve it
Issue: BAEL-2416
1 parent 65b9909 commit 0474389

21 files changed

+491
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.baeldung.concurrent.threadsafety.application;
2+
3+
import com.baeldung.concurrent.threadsafety.callables.AtomicCounterCallable;
4+
import com.baeldung.concurrent.threadsafety.mathutils.MathUtils;
5+
import com.baeldung.concurrent.threadsafety.callables.CounterCallable;
6+
import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable;
7+
import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable;
8+
import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable;
9+
import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable;
10+
import com.baeldung.concurrent.threadsafety.services.AtomicCounter;
11+
import com.baeldung.concurrent.threadsafety.services.Counter;
12+
import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter;
13+
import com.baeldung.concurrent.threadsafety.services.MessageService;
14+
import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter;
15+
import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter;
16+
import java.util.ArrayList;
17+
import java.util.Arrays;
18+
import java.util.Collection;
19+
import java.util.Collections;
20+
import java.util.Map;
21+
import java.util.concurrent.ConcurrentHashMap;
22+
import java.util.concurrent.ExecutionException;
23+
import java.util.concurrent.ExecutorService;
24+
import java.util.concurrent.Executors;
25+
import java.util.concurrent.Future;
26+
27+
public class Application {
28+
29+
public static void main(String[] args) throws InterruptedException, ExecutionException {
30+
31+
new Thread(() -> {
32+
System.out.println(MathUtils.factorial(10));
33+
}).start();
34+
new Thread(() -> {
35+
System.out.println(MathUtils.factorial(5));
36+
}).start();
37+
38+
ExecutorService executorService = Executors.newFixedThreadPool(10);
39+
MessageService messageService = new MessageService("Welcome to Baeldung!");
40+
Future<String> future1 = (Future<String>) executorService.submit(new MessageServiceCallable(messageService));
41+
Future<String> future2 = (Future<String>) executorService.submit(new MessageServiceCallable(messageService));
42+
System.out.println(future1.get());
43+
System.out.println(future2.get());
44+
45+
Counter counter = new Counter();
46+
Future<Integer> future3 = (Future<Integer>) executorService.submit(new CounterCallable(counter));
47+
Future<Integer> future4 = (Future<Integer>) executorService.submit(new CounterCallable(counter));
48+
System.out.println(future3.get());
49+
System.out.println(future4.get());
50+
51+
ExtrinsicLockCounter extrinsicLockCounter = new ExtrinsicLockCounter();
52+
Future<Integer> future5 = (Future<Integer>) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter));
53+
Future<Integer> future6 = (Future<Integer>) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter));
54+
System.out.println(future5.get());
55+
System.out.println(future6.get());
56+
57+
ReentrantLockCounter reentrantLockCounter = new ReentrantLockCounter();
58+
Future<Integer> future7 = (Future<Integer>) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter));
59+
Future<Integer> future8 = (Future<Integer>) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter));
60+
System.out.println(future7.get());
61+
System.out.println(future8.get());
62+
63+
ReentrantReadWriteLockCounter reentrantReadWriteLockCounter = new ReentrantReadWriteLockCounter();
64+
Future<Integer> future9 = (Future<Integer>) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter));
65+
Future<Integer> future10 = (Future<Integer>) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter));
66+
System.out.println(future9.get());
67+
System.out.println(future10.get());
68+
69+
AtomicCounter atomicCounter = new AtomicCounter();
70+
Future<Integer> future11 = (Future<Integer>) executorService.submit(new AtomicCounterCallable(atomicCounter));
71+
Future<Integer> future12 = (Future<Integer>) executorService.submit(new AtomicCounterCallable(atomicCounter));
72+
System.out.println(future11.get());
73+
System.out.println(future12.get());
74+
75+
Collection<Integer> syncCollection = Collections.synchronizedCollection(new ArrayList<>());
76+
Thread thread11 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)));
77+
Thread thread12 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)));
78+
thread11.start();
79+
thread12.start();
80+
81+
Map<String,String> concurrentMap = new ConcurrentHashMap<>();
82+
concurrentMap.put("1", "one");
83+
concurrentMap.put("2", "two");
84+
concurrentMap.put("3", "three");
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.baeldung.concurrent.threadsafety.callables;
2+
3+
import com.baeldung.concurrent.threadsafety.services.AtomicCounter;
4+
import java.util.concurrent.Callable;
5+
6+
public class AtomicCounterCallable implements Callable<Integer> {
7+
8+
private final AtomicCounter counter;
9+
10+
public AtomicCounterCallable(AtomicCounter counter) {
11+
this.counter = counter;
12+
}
13+
14+
@Override
15+
public Integer call() throws Exception {
16+
counter.incrementCounter();
17+
return counter.getCounter();
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.baeldung.concurrent.threadsafety.callables;
2+
3+
import com.baeldung.concurrent.threadsafety.services.Counter;
4+
import java.util.concurrent.Callable;
5+
6+
public class CounterCallable implements Callable<Integer> {
7+
8+
private final Counter counter;
9+
10+
public CounterCallable(Counter counter) {
11+
this.counter = counter;
12+
}
13+
14+
@Override
15+
public Integer call() throws Exception {
16+
counter.incrementCounter();
17+
return counter.getCounter();
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.baeldung.concurrent.threadsafety.callables;
2+
3+
import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter;
4+
import java.util.concurrent.Callable;
5+
6+
public class ExtrinsicLockCounterCallable implements Callable<Integer> {
7+
8+
private final ExtrinsicLockCounter counter;
9+
10+
public ExtrinsicLockCounterCallable(ExtrinsicLockCounter counter) {
11+
this.counter = counter;
12+
}
13+
14+
@Override
15+
public Integer call() throws Exception {
16+
counter.incrementCounter();
17+
return counter.getCounter();
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.baeldung.concurrent.threadsafety.callables;
2+
3+
import com.baeldung.concurrent.threadsafety.services.MessageService;
4+
import java.util.concurrent.Callable;
5+
6+
public class MessageServiceCallable implements Callable<String> {
7+
8+
private final MessageService messageService;
9+
10+
public MessageServiceCallable(MessageService messageService) {
11+
this.messageService = messageService;
12+
13+
}
14+
15+
@Override
16+
public String call() {
17+
return messageService.getMesssage();
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.baeldung.concurrent.threadsafety.callables;
2+
3+
import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter;
4+
import java.util.concurrent.Callable;
5+
6+
public class ReentranReadWriteLockCounterCallable implements Callable<Integer> {
7+
8+
private final ReentrantReadWriteLockCounter counter;
9+
10+
public ReentranReadWriteLockCounterCallable(ReentrantReadWriteLockCounter counter) {
11+
this.counter = counter;
12+
}
13+
14+
@Override
15+
public Integer call() throws Exception {
16+
counter.incrementCounter();
17+
return counter.getCounter();
18+
}
19+
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.baeldung.concurrent.threadsafety.callables;
2+
3+
import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter;
4+
import java.util.concurrent.Callable;
5+
6+
public class ReentrantLockCounterCallable implements Callable<Integer> {
7+
8+
private final ReentrantLockCounter counter;
9+
10+
public ReentrantLockCounterCallable(ReentrantLockCounter counter) {
11+
this.counter = counter;
12+
}
13+
14+
@Override
15+
public Integer call() throws Exception {
16+
counter.incrementCounter();
17+
return counter.getCounter();
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.baeldung.concurrent.threadsafety.mathutils;
2+
3+
import java.math.BigInteger;
4+
5+
public class MathUtils {
6+
7+
public static BigInteger factorial(int number) {
8+
BigInteger f = new BigInteger("1");
9+
for (int i = 2; i <= number; i++) {
10+
f = f.multiply(BigInteger.valueOf(i));
11+
}
12+
return f;
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
import java.util.concurrent.atomic.AtomicInteger;
4+
5+
public class AtomicCounter {
6+
7+
private final AtomicInteger counter = new AtomicInteger();
8+
9+
public AtomicCounter() {}
10+
11+
public void incrementCounter() {
12+
counter.incrementAndGet();
13+
}
14+
15+
public synchronized int getCounter() {
16+
return counter.get();
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
public class Counter {
4+
5+
private volatile int counter;
6+
7+
public Counter() {
8+
this.counter = 0;
9+
}
10+
11+
public synchronized void incrementCounter() {
12+
counter += 1;
13+
}
14+
15+
public int getCounter() {
16+
return counter;
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
public class ExtrinsicLockCounter {
4+
5+
private int counter;
6+
private final Object lock = new Object();
7+
8+
public ExtrinsicLockCounter() {
9+
this.counter = 0;
10+
}
11+
12+
public void incrementCounter() {
13+
synchronized (lock) {
14+
counter += 1;
15+
}
16+
}
17+
18+
public int getCounter() {
19+
synchronized (lock) {
20+
return counter;
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
public class MessageService {
4+
5+
private final String message;
6+
7+
public MessageService(String message) {
8+
this.message = message;
9+
}
10+
11+
public String getMesssage() {
12+
return message;
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
import java.util.concurrent.locks.ReentrantLock;
4+
5+
public class ReentrantLockCounter {
6+
7+
private int counter;
8+
private final ReentrantLock reLock = new ReentrantLock(true);
9+
10+
public ReentrantLockCounter() {
11+
this.counter = 0;
12+
}
13+
14+
public void incrementCounter() {
15+
reLock.lock();
16+
try {
17+
counter += 1;
18+
} finally {
19+
reLock.unlock();
20+
}
21+
}
22+
23+
public int getCounter() {
24+
return counter;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
import java.util.concurrent.locks.Lock;
4+
import java.util.concurrent.locks.ReentrantReadWriteLock;
5+
6+
public class ReentrantReadWriteLockCounter {
7+
8+
private int counter;
9+
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
10+
private final Lock readLock = rwLock.readLock();
11+
private final Lock writeLock = rwLock.writeLock();
12+
13+
public ReentrantReadWriteLockCounter() {
14+
this.counter = 0;
15+
}
16+
17+
public void incrementCounter() {
18+
writeLock.lock();
19+
try {
20+
counter += 1;
21+
} finally {
22+
writeLock.unlock();
23+
}
24+
}
25+
26+
public int getCounter() {
27+
readLock.lock();
28+
try {
29+
return counter;
30+
} finally {
31+
readLock.unlock();
32+
}
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.baeldung.concurrent.threadsafety.services;
2+
3+
public class StateHolder {
4+
5+
private final String state;
6+
7+
public StateHolder(String state) {
8+
this.state = state;
9+
}
10+
11+
public String getState() {
12+
return state;
13+
}
14+
}

0 commit comments

Comments
 (0)