5 Ways to turn Java synchronization of asynchronous call

1, the concept of asynchronous and synchronous

 同步调用:调用方在调用过程中,持续等待返回结果。
 异步调用:调用方在调用过程中,不直接等待返回结果,而是执行其他任务,结果返回形式通常为回调函数。

2, the probability of synchronous, asynchronous turn

  需要在异步调用过程中,持续阻塞至获得调用结果。

3, asynchronous call transfer 5 ways to synchronize

1, using the wait and notify methods
2, lock conditions
. 3, Future
. 4, using a CountDownLatch
. 5, using CyclicBarrier

4, construct an asynchronous call model.

Our main concern call method, which received a demo parameter, and opened a thread to perform specific tasks in the thread, and calls the callback function callback method using the demo. It was noted that the result is a return here [0,10) long integer, and the result is a few, let the thread sleep long - mainly in order to better observe the experimental results, the simulation processing time during the asynchronous call . As futureCall and shutdown methods, as well as tp thread pool is to be achieved demo3 use Future prepare.

   
public class AsyncCall {    
private Random random = new Random(System.currentTimeMillis());   
 private ExecutorService tp = Executors.newSingleThreadExecutor();    //demo1,2,4,5调用方法
    public void call(BaseDemo demo){        

                new Thread(()->{            long res = random.nextInt(10);            try {
                Thread.sleep(res*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            demo.callback(res);
        }).start();


    }    //demo3调用方法
    public Future<Long> futureCall(){        
            return tp.submit(()-> {          
             long res = random.nextInt(10);            try {
             Thread.sleep(res*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }            return res;
        });

    }    public void shutdown(){

        tp.shutdown();

    }

}

demo base class:

public abstract class BaseDemo {  
      protected AsyncCall asyncCall = new AsyncCall();  
      public abstract void callback(long response);  
      public void call(){
        System.out.println("发起调用");
        asyncCall.call(this);
        System.out.println("调用返回");
    }

}

5, the specific implementation of the various methods

5.1 Use wait and notify methods

Can be seen after initiating calls, the main thread by blocking the use of wait, notify or notifyAll call waiting callback method to wake up. Note that the cognitive and everyone, as here, wait and notify all need to get a lock object. Finally in the main thread we print a content, which is used to verify the results, if not wait and notify, the main thread will immediately call the contents of the print contents at once; and as we have above code, the contents of the main thread will wait callback function call ended before printing.
Without the use of synchronous operation, the print result:

public class Demo1 extends BaseDemo{    private final Object lock = new Object();    @Override
      public void callback(long response) {
        System.out.println("得到结果");
        System.out.println(response);
        System.out.println("调用结束");        synchronized (lock) {
            lock.notifyAll();
        }

    }    public static void main(String[] args) {

        Demo1 demo1 = new Demo1();

        demo1.call();        synchronized (demo1.lock){            try {
                demo1.lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("主线程内容");

    }
}

Without the use of synchronous operation, the print result:

发起调用
调用返回
主线程内容
得到结果
1
调用结束

And after using the synchronous operation:

发起调用
调用返回
得到结果
9
调用结束
主线程内容

5.2 Conditions of Use lock

And 5.2 on this method makes no difference, but here the conditions for the use of a lock, both lock mechanism is different.

public class Demo2 extends BaseDemo {  
  private final Lock lock = new ReentrantLock();    
private final Condition con = lock.newCondition();    
@Override
    public void callback(long response) {

        System.out.println("得到结果");
        System.out.println(response);
        System.out.println("调用结束");
        lock.lock();        try {
            con.signal();
        }finally {
            lock.unlock();
        }

    }    public static void main(String[] args) {

        Demo2 demo2 = new Demo2();

        demo2.call();

        demo2.lock.lock();        try {
            demo2.con.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            demo2.lock.unlock();
        }
        System.out.println("主线程内容");
    }
}

5.3、Future

Future use of the method and not the same as before, we call asynchronous methods are not the same

public class Demo3{    
    private AsyncCall asyncCall = new AsyncCall();    
    public Future<Long> call(){

        Future<Long> future = asyncCall.futureCall();

        asyncCall.shutdown();        return future;

    }    public static void main(String[] args) {

        Demo3 demo3 = new Demo3();

        System.out.println("发起调用");
        Future<Long> future = demo3.call();
        System.out.println("返回结果");      
  while (!future.isDone() && !future.isCancelled());      
  try {
            System.out.println(future.get());
        } catch (InterruptedException e)
         {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        System.out.println("主线程内容");

    }
}

5.4、CountDownLatch

Use CountDownLatch daily programming is perhaps the most common type, and also feeling relatively elegant one:

public class Demo4 extends BaseDemo{ 
   private final CountDownLatch countDownLatch = new CountDownLatch(1); 
   @Override
    public void callback(long response) {

        System.out.println("得到结果");
        System.out.println(response);
        System.out.println("调用结束");

        countDownLatch.countDown();

    }    public static void main(String[] args) {

        Demo4 demo4 = new Demo4();

        demo4.call();        try {
            demo4.countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("主线程内容");

    }

As we usually use it, here in the main line Cheng Zhongli were blocking await CountDownLatch method in the callback method to make use countDown some of the other threads to continue to await the run.
Of course, here and in the same demo1 and demo2, blocking the main thread portion, you can set a timeout after a timeout can no longer blocks

5.5、CyclicBarrier

CyclicBarrier and CountDownLatch situation is somewhat similar:

public class Demo5 extends BaseDemo{   
 private CyclicBarrier cyclicBarrier = new CyclicBarrier(2); 
   @Override
    public void callback(long response) {

        System.out.println("得到结果");
        System.out.println(response);
        System.out.println("调用结束");        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }

    }    public static void main(String[] args) {

        Demo5 demo5 = new Demo5();

        demo5.call();        try {
            demo5.cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }

        System.out.println("主线程内容");

    }
}

I have your attention, CyclicBarrier and CountDownLatch just similar, the two still have some differences. For example, a can be understood as being the addition, run together until after this number was added; is a subtraction, reduced to 0 to continue to run. It is a repeat count; the other can not be so much more.
In addition, the use of CyclicBarrier time to pay attention to two points. First, when the initialization parameter number to be set to 2, because the asynchronous call here is a thread, the main thread is a thread, two threads await when they could proceed, and this is the difference between CountDownLatch part. The second point is about the value of initialization parameter, and the demo here has nothing to do, in the usual programming, the need for more careful, if this value is set very large, larger than the number of threads in the pool, then it is easy cause deadlock.

Guess you like

Origin www.cnblogs.com/xiaohua7988/p/11616515.html