Java asynchronous query-to-sync multiple implementations: Loop wait, countdownlatch,spring even

Source: Internet
Author: User
Tags log4j

Asynchronous to synchronous business requirements

Some interface query feedback results are returned asynchronously, and query results cannot be obtained immediately.

    • Normal processing logic

Triggers an asynchronous operation, and then passes a unique identity.

Waits until the asynchronous result returns, matching the result according to the unique identity passed in.

    • How to convert to synchronous

There are a lot of normal scenarios, but sometimes you don't want to do data storage, just want to get the results of the call simply.

What if you want to achieve the results of a synchronous operation?

Ideas
    1. Initiating an asynchronous operation

    2. Wait until the asynchronous result returns (you can set the timeout)

    3. After the result is returned, the result of the asynchronous operation returns uniformly
Loop wait
    • Loopquery.java

query()when the asynchronous operation is remoteCallback() completed, it is returned synchronously.

public class Loopquery implements Async {private String result;    private static final Logger Logger = Logmanager.getlogger (LoopQuery.class.getName ());        @Override public string query (string key) {Startquery (key);            New Thread (New Runnable () {@Override public void run () {remotecallback (key);        }}). Start ();        Final String QueryResult = Endquery ();        Logger.info ("Query result: {}", queryresult);    return queryresult; }/** * Start query * @param key query condition */private void Startquery (final String key) {logger.info ("Execute query:    {} ", key); }/** * Remote callback is waiting is random * * @param key Query condition */private void Remotecallback (final String key) {T        ry {TimeUnit.SECONDS.sleep (5);        } catch (Interruptedexception e) {e.printstacktrace ();        } This.result = key + "-result";    Logger.info ("Remotecallback set result: {}", result); }    /** * End Query * @return return result */private String endquery () {while (true) {if (null = = result)                {try {TimeUnit.MILLISECONDS.sleep (100);                } catch (Interruptedexception e) {e.printstacktrace ();            }} else {return result; }        }    }}
    • Main ()
public static void main(String[] args) {    new LoopQuery().query("12345");}
    • Test results
18:14:16.491 [main] INFO  com.github.houbb.thread.learn.aysnc.loop.LoopQuery - 执行查询: 1234518:14:21.498 [Thread-1] INFO  com.github.houbb.thread.learn.aysnc.loop.LoopQuery - remoteCallback set result: 12345-result18:14:21.548 [main] INFO  com.github.houbb.thread.learn.aysnc.loop.LoopQuery - 查询结果: 12345-result
Countdownlatch
    • Asyncquery.java

Use CountDownLatch the class to achieve the effect of synchronization.

Import Org.apache.logging.log4j.logmanager;import Org.apache.logging.log4j.logger;import Java.util.concurrent.countdownlatch;import Java.util.concurrent.timeunit;public class AsyncQuery {private static    Final Logger Logger = Logmanager.getlogger (AsyncQuery.class.getName ());    /** * Result * */private String result; /** * Asynchronous to Synchronous query * @param key */public void Asyncquery (final String key) {Final Countdownlatch latch        = new Countdownlatch (1);        This.startquery (key);                New Thread (new Runnable () {@Override public void run () {logger.info ("Remote callback thread Start");                Remotecallback (key, latch);            Logger.info ("Remote Callback Thread End");        }}). Start ();        try {latch.await ();        } catch (Interruptedexception e) {e.printstacktrace ();    } this.endquery ();    } private void Startquery (final String key) {logger.info ("Execute query: {}", key); }    /**     * The remote callback is the wait is random * @param key */private void Remotecallback (Final String key, Countdownlatch latch) {try        {TimeUnit.SECONDS.sleep (5);        } catch (Interruptedexception e) {e.printstacktrace ();        } This.result = key + "-result";    Latch.countdown ();    } private void Endquery () {logger.info ("query result: {}", result); }}
    • Main ()
public static void main(String[] args) {    AsyncQuery asyncQuery = new AsyncQuery();    final String key = "123456";    asyncQuery.asyncQuery(key);}
    • Log
18:19:12.714 [main] INFO  com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 执行查询: 12345618:19:12.716 [Thread-1] INFO  com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 远程回调线程开始18:19:17.720 [main] INFO  com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 查询结果: 123456-result18:19:17.720 [Thread-1] INFO  com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 远程回调线程结束
Spring EventListener

It is also possible to use the observer pattern. (Optimization of Scenario I)

This is used in conjunction with spring.

    • Bookingcreatedevent.java

An object that defines a transport property.

public class BookingCreatedEvent extends ApplicationEvent {    private static final long serialVersionUID = -1387078212317348344L;    private String info;    public BookingCreatedEvent(Object source) {        super(source);    }    public BookingCreatedEvent(Object source, String info) {        super(source);        this.info = info;    }    public String getInfo() {        return info;    }}
    • Bookingservice.java

Description: When this.context.publishEvent(bookingCreatedEvent); triggered,
Will be @EventListener heard by the designated method.

Import Org.springframework.beans.factory.annotation.autowired;import Org.springframework.context.applicationcontext;import Org.springframework.context.event.eventlistener;import Org.springframework.stereotype.service;import java.util.concurrent.TimeUnit; @Servicepublic class Bookingservice {@    autowired private ApplicationContext context;    private volatile bookingcreatedevent bookingcreatedevent; /** * Asynchronous to Synchronous query * @param info * @return */public string asyncquery (final String info) {query (INF        O);            New Thread (New Runnable () {@Override public void run () {remotecallback (info);        }}). Start ();            while (bookingcreatedevent = = null) {//: Empty loop//short wait.            try {TimeUnit.MILLISECONDS.sleep (1);            } catch (Interruptedexception e) {//...} 2.        Use two separate event ...} Final String result = BookingcreAtedevent.getinfo ();        Bookingcreatedevent = null;    return result; } @EventListener public void Onapplicationevent (Bookingcreatedevent bookingcreatedevent) {System.out.println        ("Listen to remote information:" + bookingcreatedevent.getinfo ());        This.bookingcreatedevent = bookingcreatedevent;    System.out.println ("After hearing the remote message:" + this.bookingCreatedEvent.getInfo ()); /** * Execute Query * @param info */public void query (final String info) {System.out.println ("Start query:")    + info); }/** * Remote callback * @param info */public void Remotecallback (final String info) {System.out.println (        "Remote callback Start:" + info);        try {TimeUnit.SECONDS.sleep (2);        } catch (Interruptedexception e) {e.printstacktrace ();        }//re-send result event String result = info + "-result";        Bookingcreatedevent bookingcreatedevent = new Bookingcreatedevent (this, result); Trigger Event This.context.publishEvent (bookingCreatedevent); }}
    • Test method
@RunWith(SpringJUnit4Cla***unner.class)@ContextConfiguration(classes = SpringConfig.class)public class BookServiceTest {    @Autowired    private BookingService bookingService;    @Test    public void asyncQueryTest() {        bookingService.asyncQuery("1234");    }}
    • Log
2018-08-10 18:27:05.958  INFO  [main] com.github.houbb.spring.lean.core.ioc.event.BookingService:84 - 开始查询:12342018-08-10 18:27:05.959  INFO  [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:93 - 远程回调开始:1234接收到信息: 1234-result2018-08-10 18:27:07.964  INFO  [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:73 - 监听到远程的信息: 1234-result2018-08-10 18:27:07.964  INFO  [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:75 - 监听到远程消息后: 1234-result2018-08-10 18:27:07.964  INFO  [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:106 - 已经触发event2018-08-10 18:27:07.964  INFO  [main] com.github.houbb.spring.lean.core.ioc.event.BookingService:67 - 查询结果: 1234-result2018-08-10 18:27:07.968  INFO  [Thread-1] org.springframework.context.support.GenericApplicationContext:993 - Closing [email protected]ee5251: startup date [Fri Aug 10 18:27:05 CST 2018]; root of context hierarchy
Timeout and empty loop empty loop

Empty loops can cause the CPU to soar

while(true) {}
    • How to Solve
while(true) {    // 小睡即可    TimeUnit.sleep(1);}
Time-out writing

It is not possible to wait for feedback and set the time-out.

 /** * loops until results are obtained * @param key key * @param timeoutinseconds timeout * @param <T> generics * @return results. Throws an exception if timed out */public <T> T loopwaitforvalue (Final String key, long timeoutinseconds) {Long startTime = System.nano    Time ();    Long deadline = StartTime + TimeUnit.SECONDS.toNanos (timeoutinseconds); 1. If there is no new callback, or the key corresponding element does not exist.        The loop is cycled while (Objectutil.isnull (Map.get (key))) {try {TimeUnit.MILLISECONDS.sleep (5);        } catch (Interruptedexception e) {logger.warn ("Loop meet interruptedexception, just ignore it.", e);        }//Timeout to judge long currenttime = System.nanotime ();        if (currenttime >= deadline) {throw new bussinessexception (errorcode.read_time_out);    }} final T target = (t) map.get (key);    Logger.debug ("Loopwaitforvalue get value:{} for key:{}", Json.tojson (target), key); 2.    After getting to the element, you need to remove the corresponding value map.remove (key); return target;}  
Code address

Loop

Countdownlatch

Spring-event-listener

Java asynchronous query-to-sync multiple implementations: Loop wait, countdownlatch,spring even

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.