Thursday, July 13, 2017

Utility Classes under Java util.concurrent package


When you check the java util.concurrent package , there are some utility classes provided , after removing lots of abstract classes which is useless for our users. we may notice couple of them are quite useful in our work. I will describle the most popular 4 utility classes here in this article;

CountDownLatch : this classes normally will be used to monitor some initializations ,  after some initializations , it will help to inform the main thread to continues to do its job. for example : in zookeeper, in the begining, web connection will be firstly established and some instances will be initialised then. Thus initialization will be done after connection is establised. So this behavious will be monitored and informed by CountDownLatch



 final CountDownLatch countDown = new CountDownLatch(2);
 Thread t1 = new Thread(new Runnable() {
  @Override
  public void run() {
      try {
            System.out.println("enter thread t1" + "waiting for other threa                                            d to finish...");
            countDown.await(); 
             // wait & block here,because new CountDownLatch(2), so if ther                           e are 2 threads making countDown signal, this thread will 
                continues to go 
            System.out.println("t1 thread continues to go...");
   } catch (InterruptedException e) {
            e.printStackTrace();
    }}},"t1");
  
 Thread t2 = new Thread(new Runnable() {
   @Override
   public void run() {
      try {
           System.out.println("t2 initialise...");
           Thread.sleep(3000); // sleep
           System.out.println("t2 finishs init,inform t1 to continue...");
           countDown.countDown(); // make a countdown signal
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
   }});
  Thread t3 = new Thread(new Runnable() {
   @Override
   public void run() {
      try {
          System.out.println("t3 initialise...");
          Thread.sleep(4000);
          System.out.println("t3 finish the init,inform t1 to continue..");
          countDown.countDown(); // make a countdown signal
    } catch (InterruptedException e) {
          e.printStackTrace();
    }
   }
  });
  
  t1.start();
  t2.start();
  t3.start();

CyclicBarrierThreads must all ready , then they can go , if any one thread is not ready. all other threads must wait for it .


static class Runner implements Runnable {  
     private CyclicBarrier barrier;  
     private String name;  
     
     public Runner(CyclicBarrier barrier, String name) {  
         this.barrier = barrier;  
         this.name = name;  
     }  
     @Override  
     public void run() {  
         try {  
             Thread.sleep(1000 * (new Random()).nextInt(5));  
             System.out.println(name + " ready OK.");  
             barrier.await();  // wait,new CyclicBarrier(3),3 athletes must be
                                         all ready = await() is called 3 times , 
         } catch (InterruptedException e) {  
             e.printStackTrace();  
         } catch (BrokenBarrierException e) {  
             e.printStackTrace();  
         }  
         System.out.println(name + " Go!!");  
     }  
 } 
 
    public static void main(String[] args) throws IOException, InterruptedException {  
        CyclicBarrier barrier = new CyclicBarrier(3);  // 3 athlets , called 3 times 
        ExecutorService executor = Executors.newFixedThreadPool(3);  
        
        executor.submit(new Thread(new Runner(barrier, "john")));  
        executor.submit(new Thread(new Runner(barrier, "peter")));  
        executor.submit(new Thread(new Runner(barrier, "luci")));  
  
        executor.shutdown();  
    }  

Differences :
   CountDownLatch is one thread waiting for other N threads information, then in the end one thread run
   CyclicBarrier is multiple threads wait for one another and all run together in the end.

Semaphore : = ticket checker / bus conductor, which is used to limit the threads in high concurrency.


        // thread pool 
        ExecutorService exec = Executors.newCachedThreadPool();  
        // only allow 5 threads visit simoutanously  
        final Semaphore semp = new Semaphore(5);  
        // simulate 10 clients visit  
        for (int index = 0; index < 20; index++) {  
            final int NO = index;  
            Runnable run = new Runnable() {  
                public void run() {  
                    try {  
                        // acquire ticket,only 5 threads can be in,once there is a sl                          ot, then another thread can be let in ,limit the stream。
                        semp.acquire();  
                        System.out.println("Accessing: " + NO);  
                        //simuate real business logic
                        Thread.sleep((long) (Math.random() * 10000));  
                        // after visit, release resource.  
                        semp.release();  
                    } catch (InterruptedException e) {  
                    }  
                }  
            };  
            exec.execute(run);  
        } 
        
        try {
   Thread.sleep(10);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
        
        //System.out.println(semp.getQueueLength());
         
        // exit thread pool 
        exec.shutdown();  
    }  

Future : used for a request waiting for response for a long time. so future will create a thread to fetch the data asyncronously and this dones't block the main thread to run. once future thread is finished, you can come back and check the data later.



private String para;
 
 public UseFuture(String para){
  this.para = para;
 }
 
 /**
  * simulate real business logic, very time-consuming
  */
 @Override
 public String call() throws Exception {
  //simulate a time consuming request
  Thread.sleep(5000);
  String result = this.para + "process finished";
  return result;
 }
 
 //main method
 public static void main(String[] args) throws Exception {
 String queryStr = "query";
 //FutureTask,pass in a business logic,this class implement Callable
 FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr));
  
 FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr));
 //create a thread pool
 ExecutorService executor = Executors.newFixedThreadPool(2);
   
 Future f1 = executor.submit(future);
 Future f2 = executor.submit(future2);
 System.out.println("request finished");
  
 try {
  //this part can do the main business logic
  System.out.println("process real business logic...");
  Thread.sleep(1000);
 } catch (Exception e) {
  e.printStackTrace();
 }
 //call and get the data,if call() hasn't finished,it will block and wait,
          FutureTask is asyncronous。aaa will print first, future will print second
 System.out.println("data:" + future.get());
 System.out.println("data:" + future2.get());
        System.out.println("aaa"); 
 executor.shutdown();

No comments:

Post a Comment

Add Loading Spinner for web request.

when web page is busily loading. normally we need to add a spinner for the user to kill their waiting impatience. Here, 2 steps we need to d...