Saturday, September 6, 2014

4. Multiple Locks Using Synchronized Code Blocks

Java Multithreading: Lock Objects
This is the fourth part of our advanced Java multi-threading tutorial. In this tutorial I show you how you can use multiple locks to speed up complex multi-threaded code, sometimes dramatically.

Code For This Tutorial
App.java:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class App {
       
    public static void main(String[] args) {
        Worker worker = new Worker();
        worker.main();

    }

}

Using Synchonized Methods
class Worker {

      private Random random = new Random();

      private List<Integer> list1 = new ArrayList<Integer>();
      private List<Integer> list2 = new ArrayList<Integer>();

      public synchronized void stageOne() {

            try {
                  Thread.sleep(1);
            } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }

            list1.add(random.nextInt(100));

      }

      public synchronized void stageTwo() {

            try {
                  Thread.sleep(1);
            } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }

            list2.add(random.nextInt(100));
      }

      public void process() {
            for (int i = 0; i < 1000; i++) {
                  stageOne();
                  stageTwo();
            }
      }

      public void main() {
            System.out.println("Starting ...");

            long start = System.currentTimeMillis();

            Thread t1 = new Thread(new Runnable() {
                  public void run() {
                        process();
                  }
            });

            Thread t2 = new Thread(new Runnable() {
                  public void run() {
                        process();
                  }
            });

            t1.start();
            t2.start();

            try {
                  t1.join();
                  t2.join();
            } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }

            long end = System.currentTimeMillis();

            System.out.println("Time taken: " + (end - start));
            System.out.println("List1: " + list1.size() + "; List2: "
                        + list2.size());
      }
}
Output:
Starting ...
Time taken: 4413
List1: 2000; List2: 2000

Time taken to execute thread is Approx 4secs because while running one synchronized method it will not allow to run other methods due to lock on object.

class Worker {
    
    private Random random = new Random();
    
    private Object lock1 = new Object();
    private Object lock2 = new Object();
    
    private List<Integer> list1 = new ArrayList<Integer>();
    private List<Integer> list2 = new ArrayList<Integer>();
    
    public void stageOne() {
        
        synchronized (lock1) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            list1.add(random.nextInt(100));
        }
    
    }
    
    public void stageTwo() {
        
        synchronized (lock2) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            list2.add(random.nextInt(100));
        }
        
    }
    
    public void process() {
        for(int i=0; i<1000; i++) {
            stageOne();
            stageTwo();
        }
    }

    public void main() {
        System.out.println("Starting ...");
        
        long start = System.currentTimeMillis();
        
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                process();
            }
        });
        
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                process();
            }
        });
        
        t1.start();
        t2.start();
        
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        long end = System.currentTimeMillis();
        
        System.out.println("Time taken: " + (end - start));
        System.out.println("List1: " + list1.size() + "; List2: " + list2.size());
    }
}
Output:
Starting ...
Time taken: 2022
List1: 2000; List2: 2000

Time taken to execute threads is Approx 2secs because here two threads run parallel, load will on CPU. Synchronized block will not acquire lock on object.



No comments:

Post a Comment