Tuesday 16 June 2015

Part 3. Thread in Java: Thread synchronization (or thread safe)

Part 3. Thread synchronization (or thread safe)
In summary, synchronization helps sharing data (by multiple threads) consistency.
We know that, in multiple threading application, all the threads may share one or more resource across application. For example, they may share a queue/list contains data about employee to process, one or more threads are used to read data from another resource, and put it into this queue, and one or more threads are used to process data in this queue. In the multi-threaded application, it is very important to consist sharing data. One data cannot be processed more than one time. In this case, we use synchronization in java to solve problem.
Note: sometime they call this as thread-safe.
There are two ways to synchronize resource: synchronize block and synchronize methods.
  1. Synchronize block:
synchronized (resource) {
}
Where: resource is an object that are used to share between threads.
  1. Synchronize methods:
public synchronized void put(Object data){
//other stuff
}
public synchronized Object get(){
//other stuff
return null;
}
These two methods are one of resource “container” where you want to share between threads.
Example, we have one thread for pushing data, and two threads for getting data. The first getting data thread will wait 0.5 second for each time take the data, the second getting data thread waits only 0.3 second.
Note that, in this example, I used LinkedList as a sharing resource between threads, hence I have to use synchronized block. However, there are many List (Vector), Queue (like ConcurrentLinkedList) can be used instead, it already provided synchronized methods.
import java.util.LinkedList;

public class SynchronizeDemo {
public static void main(String[] args) {
LinkedList resources = new LinkedList();
PusherThread pt = new PusherThread(resources, 300);
pt.start();

PrinterThread print1 = new PrinterThread(resources, "Print1", 300);
PrinterThread print2 = new PrinterThread(resources, "Print2", 200);
print1.start();
print2.start();
System.out.println("All threads are started!!!!");
}

}

class PusherThread extends Thread {
private LinkedList rs;

public PusherThread(LinkedList rs, int no) {
this.noOfElement = no;
this.rs = rs;
}

private int noOfElement = 10;

public void run() {
for (int i = 0; i < noOfElement; i++) {
synchronized (rs) {
rs.add(i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
}
}
}
System.out.println(noOfElement + " numbers are added to the list!");
}
}

class PrinterThread extends Thread {
private LinkedList rs;

public PrinterThread(LinkedList rs, String name, long sleepTime) {
this.rs = rs;
this.sleepTime = sleepTime;
this.threadName = name;
}

private boolean start = true;
private long sleepTime = 100;

public void stop(boolean val) {
this.start = val;
}

public void sleepIn(long val) {
this.sleepTime = val;
}

private String threadName;

public void nameMe(String val) {
this.threadName = val;
}

public void run() {
while (start) {
// synchronize helps us only one value is removed
synchronized (rs) {
if (!rs.isEmpty()) {
int val = rs.remove();// remove a value
System.out.println("[" + threadName + "], Removed :" + val);
}
}
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
}
}
Output:
As result from program, we don’t know when the linked list object is empty. If we don’t set the “start” Boolean to false, these PrinterThread will run forever. To solve this problem, we use Wait/notify mechanism. Reading next post: Part 4. Wait/notify mechanism.

No comments:

Post a Comment