Skip to content

Commit c6a7727

Browse files
author
Leonardo Henrique Zapparoli
committed
fixes, migrating from threads to executors and atomics
1 parent 4add7e6 commit c6a7727

17 files changed

+151
-41
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Concurrency Patterns and features found in Java, through multithreaded programmi
2424
* Cached Thread Pool
2525
* Single Thread Pool
2626
* Scheduled Thread Pool
27+
* Atomics
2728

2829
## Patterns
2930
* Protect Shared State
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package br.com.leonardoz.features.atomics;
2+
3+
import java.util.concurrent.ExecutorService;
4+
import java.util.concurrent.Executors;
5+
import java.util.concurrent.TimeUnit;
6+
import java.util.concurrent.atomic.AtomicInteger;
7+
8+
/**
9+
* Atomics can be used from the java.util.concurrent.atomic.* package.
10+
*
11+
* An atomic operation is a compound action that totally completes out totally
12+
* fails, not supporting inconsistent values or results during it's execution.
13+
*
14+
* The classes in this package supports atomic operations on single variables,
15+
* having get and set (read and write) methods that behave like a volatile
16+
* variable.
17+
*
18+
* The compareAndSet are commonly used in non-blocking algorithms. They
19+
* basically tries to set a new value to a specified field, and it returns a
20+
* boolean indicating success or not. All atomic, only blocking briefly.
21+
*
22+
* Interesting classes in this package are: AtomicBoolean, AtomicLong,
23+
* AtomicReference<T>, AtomicMarkablereference<T> and
24+
* AtomicReferenceFieldUpdater<T, V>.
25+
*
26+
*
27+
*/
28+
public class UsingAtomics {
29+
30+
/*
31+
* A Counter using AtomicInteger
32+
*/
33+
static class AtomicCounter {
34+
private AtomicInteger atomicInteger = new AtomicInteger(0);
35+
36+
public void increment() {
37+
atomicInteger.incrementAndGet();
38+
}
39+
40+
public void decrement() {
41+
atomicInteger.decrementAndGet();
42+
}
43+
44+
public int get() {
45+
return atomicInteger.get();
46+
}
47+
}
48+
49+
public static void main(String[] args) throws InterruptedException {
50+
AtomicCounter counter = new AtomicCounter();
51+
ExecutorService ctp = Executors.newCachedThreadPool();
52+
for (int i = 0; i < 10_000; i++) {
53+
ctp.execute(() -> counter.increment());
54+
}
55+
ctp.shutdown();
56+
ctp.awaitTermination(4000, TimeUnit.SECONDS);
57+
System.out.println("Result shound be 10000: Actual result is: " + counter.get());
58+
}
59+
}

src/main/java/br/com/leonardoz/features/collections/UsingConcurrentCollections.java

+21-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
import java.util.concurrent.BlockingQueue;
66
import java.util.concurrent.ConcurrentHashMap;
77
import java.util.concurrent.CopyOnWriteArrayList;
8+
import java.util.concurrent.ExecutorService;
9+
import java.util.concurrent.Executors;
810
import java.util.concurrent.LinkedBlockingQueue;
11+
import java.util.concurrent.TimeUnit;
912

1013
/**
1114
* Concurrent collections are an alternative to the Synchronized Collections.
@@ -35,6 +38,7 @@ public class UsingConcurrentCollections {
3538
* - Just a few Writers can modify it.
3639
*/
3740
public static void usingConcurrentHashMap() {
41+
ExecutorService executor = Executors.newCachedThreadPool();
3842
System.out.println("=== ConcurrentHashMap ===");
3943
Random random = new Random();
4044
ConcurrentHashMap<UUID, Integer> valuesPerUuid = new ConcurrentHashMap<>();
@@ -45,18 +49,22 @@ public static void usingConcurrentHashMap() {
4549
for (int i = 0; i < 100; i++) {
4650
if (i % 6 == 0) {
4751
// write
48-
new Thread(() -> {
52+
executor.execute(() -> {
4953
UUID uuid = UUID.randomUUID();
5054
Integer value = random.nextInt(10);
5155
System.out.println("Added " + uuid + " - " + value);
5256
valuesPerUuid.putIfAbsent(uuid, value);
53-
}).start();
57+
});
5458
} else {
5559
// read
56-
new Thread(() -> System.out.println("Printed " + valuesPerUuid.values().toString())).start();
60+
executor.execute(() -> System.out.println("Printed " + valuesPerUuid.values().toString()));
5761
}
5862
}
63+
64+
// Finishing
65+
executor.shutdown();
5966
try {
67+
executor.awaitTermination(2000, TimeUnit.SECONDS);
6068
// space for other examples
6169
Thread.sleep(2000);
6270
System.out.println("\n\n\n\n");
@@ -79,6 +87,7 @@ public static void usingConcurrentHashMap() {
7987
*
8088
*/
8189
public static void usingCopyOnWriteArrayList() {
90+
ExecutorService executor = Executors.newCachedThreadPool();
8291
System.out.println("=== CopyOnWriteArrayList ===");
8392
Random random = new Random();
8493
// No ConcurrentModificationException
@@ -87,23 +96,27 @@ public static void usingCopyOnWriteArrayList() {
8796
for (int i = 0; i < 100; i++) {
8897
if (i % 8 == 0) {
8998
// write
90-
new Thread(() -> {
99+
executor.execute(() -> {
91100
Integer value = random.nextInt(10);
92101
System.err.println("Added " + value);
93102
copyOnWriteArrayList.add(value);
94-
}).start();
103+
});
95104
} else {
96105
// read
97-
new Thread(() -> {
106+
executor.execute(() -> {
98107
StringBuilder sb = new StringBuilder();
99108
for (Integer vv : copyOnWriteArrayList) {
100109
sb.append(vv + " ");
101110
}
102111
System.out.println("Reading " + sb.toString());
103-
}).start();
112+
});
104113
}
105114
}
115+
116+
// Finishing
117+
executor.shutdown();
106118
try {
119+
executor.awaitTermination(2000, TimeUnit.SECONDS);
107120
// space for other examples
108121
Thread.sleep(2000);
109122
System.out.println("\n\n\n\n");
@@ -168,7 +181,7 @@ public static void usingBlockingQueue() {
168181
}
169182
};
170183

171-
// Multiple producers
184+
// Multiple producers - Examples using simple threads this time.
172185
Thread producer1 = new Thread(runProducer);
173186
producer1.start();
174187
Thread producer2 = new Thread(runProducer);

src/main/java/br/com/leonardoz/features/collections/UsingSynchronizedCollections.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package br.com.leonardoz.features.collections;
22

33
import java.util.Vector;
4+
import java.util.concurrent.ExecutorService;
5+
import java.util.concurrent.Executors;
6+
import java.util.concurrent.TimeUnit;
47

58
/**
69
* Synchronized collections synchronizes every public method to encapsulate
@@ -47,7 +50,8 @@ public static void insertIfAbsentUnsafe(Vector<Long> list, Long value) {
4750
}
4851
}
4952

50-
public static void main(String[] args) {
53+
public static void main(String[] args) throws InterruptedException {
54+
ExecutorService executor = Executors.newCachedThreadPool();
5155
// Synchronized - Vector
5256
Vector<Long> vec = new Vector<>();
5357

@@ -56,8 +60,10 @@ public static void main(String[] args) {
5660
insertIfAbsent(vec, millis);
5761
};
5862
for (int i = 0; i < 10001; i++) {
59-
new Thread(insertIfAbsent).start();
63+
executor.execute(insertIfAbsent);
6064
}
65+
executor.shutdown();
66+
executor.awaitTermination(4000, TimeUnit.SECONDS);
6167

6268
// Using the wrappers for not sync collections
6369
// List<String> synchronizedList = Collections.synchronizedList(abcList);

src/main/java/br/com/leonardoz/features/locks/UsingExplicitReadWriteLocks.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.util.Random;
44
import java.util.UUID;
5+
import java.util.concurrent.ExecutorService;
6+
import java.util.concurrent.Executors;
57
import java.util.concurrent.locks.ReentrantReadWriteLock;
68
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
79
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -63,24 +65,26 @@ public void writeContent(String newContentToAppend) {
6365
}
6466

6567
public static void main(String[] args) {
68+
ExecutorService executor = Executors.newCachedThreadPool();
6669
UsingExplicitReadWriteLocks uerwl = new UsingExplicitReadWriteLocks();
6770
// Readers
6871
for (int i = 0; i < 100; i++) {
69-
new Thread(() -> {
72+
executor.submit(() -> {
7073
try {
7174
// Delay readers to start
7275
Thread.sleep(new Random().nextInt(10) * 100);
7376
} catch (InterruptedException e) {
7477
e.printStackTrace();
7578
}
7679
System.out.println(uerwl.showContent());
77-
}).start();
80+
});
7881
}
7982

8083
// Writers - only if no writer is available
8184
for (int i = 0; i < 5; i++) {
82-
new Thread(() -> uerwl.writeContent(UUID.randomUUID().toString())).start();
85+
executor.execute(() -> uerwl.writeContent(UUID.randomUUID().toString()));
8386
}
87+
executor.shutdown();
8488
}
8589

8690
}

src/main/java/br/com/leonardoz/features/locks/UsingExplicitReentrantLocks.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package br.com.leonardoz.features.locks;
22

3+
import java.util.concurrent.ExecutorService;
4+
import java.util.concurrent.Executors;
35
import java.util.concurrent.TimeUnit;
46
import java.util.concurrent.locks.ReentrantLock;
57

@@ -58,20 +60,22 @@ public void lockMyHearthWithTiming() throws InterruptedException {
5860
}
5961

6062
public static void main(String[] args) {
63+
ExecutorService executor = Executors.newCachedThreadPool();
6164
UsingExplicitReentrantLocks uel = new UsingExplicitReentrantLocks();
6265
for (int i = 0; i < 10; i++) {
63-
new Thread(() -> uel.lockMyHearth()).start();
66+
executor.execute(() -> uel.lockMyHearth());
6467
}
6568

6669
for (int i = 0; i < 40; i++) {
67-
new Thread(() -> {
70+
executor.execute(() -> {
6871
try {
6972
uel.lockMyHearthWithTiming();
7073
} catch (InterruptedException e) {
7174
e.printStackTrace();
7275
}
73-
}).start();
76+
});
7477
}
78+
executor.shutdown();
7579
}
7680

7781
}

src/main/java/br/com/leonardoz/features/locks/UsingIntrinsicLocks.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package br.com.leonardoz.features.locks;
22

3+
import java.util.concurrent.ExecutorService;
4+
import java.util.concurrent.Executors;
5+
36
/**
47
* Every Java object has an intrinsic lock (or a monitor lock) associated with
58
* it.
@@ -66,19 +69,20 @@ public synchronized void reentrancy() {
6669
}
6770

6871
public static void main(String[] args) throws InterruptedException {
72+
ExecutorService executor = Executors.newCachedThreadPool();
6973
UsingIntrinsicLocks uil = new UsingIntrinsicLocks();
7074
for (int i = 0; i < 100; i++) {
71-
new Thread(() -> uil.mySynchronizedMethod()).start();
75+
executor.execute(() -> uil.mySynchronizedMethod());
7276
}
7377
Thread.sleep(1000);
7478
for (int i = 0; i < 10; i++) {
75-
new Thread(() -> uil.mySynchronizedBlock()).start();
79+
executor.execute(() -> uil.mySynchronizedBlock());
7680
}
7781
Thread.sleep(1000);
7882
for (int i = 0; i < 10; i++) {
79-
new Thread(() -> uil.reentrancy()).start();
83+
executor.execute(() -> uil.reentrancy());
8084
}
81-
85+
executor.shutdown();
8286
}
8387

8488
}

src/main/java/br/com/leonardoz/features/synchronizers/UsingBarriers.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.util.Random;
44
import java.util.concurrent.BrokenBarrierException;
55
import java.util.concurrent.CyclicBarrier;
6+
import java.util.concurrent.ExecutorService;
7+
import java.util.concurrent.Executors;
68

79
/**
810
* Barriers are used for blocking a group of threads until they come together at
@@ -17,6 +19,8 @@
1719
public class UsingBarriers {
1820

1921
public static void main(String[] args) {
22+
23+
ExecutorService executor = Executors.newCachedThreadPool();
2024
Runnable barrierAction = () -> System.out.println("Well done, guys!");
2125

2226
CyclicBarrier barrier = new CyclicBarrier(10, barrierAction);
@@ -34,8 +38,9 @@ public static void main(String[] args) {
3438
};
3539

3640
for (int i = 0; i < 10; i++) {
37-
new Thread(task).start();
41+
executor.execute(task);
3842
}
43+
executor.shutdown();
3944

4045
}
4146

src/main/java/br/com/leonardoz/features/synchronizers/UsingFutureTasks.java

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static void main(String[] args) {
4040
} catch (InterruptedException | ExecutionException | TimeoutException e) {
4141
e.printStackTrace();
4242
}
43+
executor.shutdown();
4344
}
4445

4546
}

src/main/java/br/com/leonardoz/features/synchronizers/UsingLatches.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package br.com.leonardoz.features.synchronizers;
22

33
import java.util.concurrent.CountDownLatch;
4+
import java.util.concurrent.ExecutorService;
5+
import java.util.concurrent.Executors;
46
import java.util.concurrent.TimeUnit;
57

68
/**
@@ -17,6 +19,7 @@
1719
public class UsingLatches {
1820

1921
public static void main(String[] args) {
22+
ExecutorService executor = Executors.newCachedThreadPool();
2023
CountDownLatch latch = new CountDownLatch(3);
2124
Runnable r = () -> {
2225
try {
@@ -27,15 +30,16 @@ public static void main(String[] args) {
2730
e.printStackTrace();
2831
}
2932
};
30-
new Thread(r).start();
31-
new Thread(r).start();
32-
new Thread(r).start();
33+
executor.execute(r);
34+
executor.execute(r);
35+
executor.execute(r);
3336
try {
3437
latch.await(2, TimeUnit.SECONDS);
3538
System.out.println("All services up and running!");
3639
} catch (InterruptedException e) {
3740
e.printStackTrace();
3841
}
42+
executor.shutdown();
3943
}
4044

4145
}

0 commit comments

Comments
 (0)