Here's an example of threads. Threads can be created by extending the Thread class and overriding the run() method, or implementing a runnable and passing it to the Thread's constructor.
In this example, we implement the Runnable class.
Explicit synchronization/care should be taken to perform thread-unsafe operations. In this case, the access to the ThreadUnsafeCounter is explicity synchronized in CounterIncrementor. Try commenting out the synchronize block and see the results.
Checkout the code
here.
public class ThreadUnsafeCounter {
|
|
private int count = 0;
|
|
public int getCount() {
|
return count;
|
}
|
|
// unsafe when multiple threads try to increment at the same time.
|
// ALL callers need to use ensure that they do not call increment at the same
|
// time. This may be done using explicit synchronize blocks.
|
public void increment() {
|
count++;
|
}
|
}
public class ThreadSafeCounter extends ThreadUnsafeCounter {
|
|
// synchronized makes it safe to call increment() in different threads without
|
// explicit locking/synchronization. the jvm with assure that only one call of
|
// increment() on an instance of ThreadSafeCounter is running at any given time.
|
@Override
|
synchronized public void increment() {
|
super.increment();
|
}
|
}
/** |
* Increments the given counters a given number of times. |
* |
* @author megha |
*/
|
public class CounterIncrementor implements Runnable {
|
|
private final int times;
|
private final ThreadSafeCounter safeCounter;
|
private final ThreadUnsafeCounter unsafeCounter;
|
|
public CounterIncrementor(ThreadUnsafeCounter unsafeCounter,
|
ThreadSafeCounter safeCounter, int times) {
|
this.unsafeCounter = unsafeCounter;
|
this.safeCounter = safeCounter;
|
this.times = times;
|
}
|
|
@Override
|
public void run() {
|
for(int i = 0; i < times; i++) {
|
safeCounter.increment();
|
// need to run in a synchronized block to ensure that two
|
// parallel calls to increment are never made
|
synchronized (unsafeCounter) {
|
unsafeCounter.increment();
|
}
|
}
|
}
|
}
import java.util.ArrayList;
|
import java.util.List;
|
|
public class Main {
|
|
public static void main(String args[]) throws InterruptedException{
|
|
ThreadUnsafeCounter unsafeCounter = new ThreadUnsafeCounter();
|
ThreadSafeCounter safeCounter = new ThreadSafeCounter();
|
CounterIncrementor incrementor =
|
new CounterIncrementor(unsafeCounter, safeCounter, 10000);
|
|
List<Thread> threads = new ArrayList<Thread>();
|
// start lots of parallel threads that increment the counter(s)
|
for (int i = 0; i < 100; i++) {
|
Thread thread = new Thread(incrementor);
|
thread.start();
|
threads.add(thread);
|
}
|
|
// wait for all threads to finish
|
for (Thread thread: threads) {
|
thread.join();
|
}
|
|
// count on unsafe counter matches that of safe counter because
|
// CounterIncrement increments unsafeCounter in a safe manner
|
System.out.println(unsafeCounter.getCount());
|
System.out.println(safeCounter.getCount());
|
}
|
} |
|
|
|