forked from javakurssi/Tuntimateriaalit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThreadSafetyExample.java
More file actions
90 lines (73 loc) · 2.91 KB
/
Copy pathThreadSafetyExample.java
File metadata and controls
90 lines (73 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package lesson8.thread;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import lesson8.thread.helpers.IDGenerator;
import lesson8.thread.helpers.IDGeneratorSync;
/**
* Example of unsafe threading where multiple threads may potentially modify the
* same memory area, leading to unexpected results. In this case multiple
* threads generate an ID by using an increasing integer value. In a problematic
* scenario the same ID is generated multiple times.
*
* The correct way is to use code block locking with the synchronized keyword,
* which is done in the commented parts of this example using the
* IDGeneratorSync class.
*/
public class ThreadSafetyExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
/**
* Count of generated IDs in both of the two threads is determined by the
* numberOfGeneratedIds variables. We don't want the same ID to be generated
* multiple times!
*/
int numberOfGeneratedIds = 50;
BackgroundTask taskA = new BackgroundTask(numberOfGeneratedIds);
BackgroundTask taskB = new BackgroundTask(numberOfGeneratedIds);
Thread t1 = new Thread(taskA);
Thread t2 = new Thread(taskB);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
IDGenerator idg = IDGenerator.getIDGenerator();
//IDGeneratorSync idg = IDGeneratorSync.getIDGenerator();
// The next id should be 2 * numberOfGeneratedIds every time we run the program
int id = idg.getLastId();
System.out.println("Final ID is: " + id);
System.out.println("Final ID should be: " + 2 * numberOfGeneratedIds);
}
}
class BackgroundTask implements Runnable {
private int numberOfGeneratedIds;
public BackgroundTask(int numberOfGeneratedIds) {
this.numberOfGeneratedIds = numberOfGeneratedIds;
}
@Override
public void run() {
IDGenerator idg = IDGenerator.getIDGenerator();
/**
* The correct implementation should only allow generating the ID one thread at
* a time. This can be done using the syncronized keyword in the method, which
* is used in the nextID method of the IDGeneratorSync class
*/
//IDGeneratorSync idg = IDGeneratorSync.getIDGenerator();
for (int i = 0; i < numberOfGeneratedIds; i++) {
// Generate a new ID
int id = idg.nextID();
System.out.println(id);
sleepRandomTime();
}
}
private void sleepRandomTime() {
Random randomGenerator = new Random();
try {
Thread.sleep(randomGenerator.nextInt(50));
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}