替换线程的繁忙循环和睡眠

时间:2018-07-01 07:02:16

标签: java multithreading

我有一个调用特定服务的线程。 该服务定义了一个可以多次调用的回调函数 只要有onProcessing()上的数据。

onCompletion()完​​成后将被调用。

public CallThread implements Runnable{
    public boolean isCompleted = false;
    public void run(){
        ResponseObserver response = new ResponseObserver(){ 
            public void onException(){
                //Errors could happen sometimes so the program should just issue another request
            }
            public void onCompletion(){
                isCompleted = true;
                //process the result
            }
            public void onProcessing(){
                //This could be called multiple time
            }
        }

            //Service is the object that calls the service
        Service service = getService();

        while(!isCompleted){
            //Request object is populated
            Request request = supplyRequest();

            service.getDetails(request, response);

            //How to remove this sleep
            Thread.sleep(10 * 1000);
        }
    }
}

我创建了一个忙循环,该循环检查isCompleted并使其进入睡眠状态。 我现在正在做的..是使用sleep命令来完成该功能 直到发出下一个请求。

我不确定这是否是最佳选择,因为有时候..它不需要10秒钟 onCompletion()被调用。 我只是想让服务返回一些东西,然后才能发出另一个请求。

有没有一种方法可以优化我的代码?

2 个答案:

答案 0 :(得分:3)

CountDownLatchCompletableFuture可用于异步等待条件:

public CallThread implements Runnable {
    public boolean isCompleted = false;

    @Override
    public void run() {
        // Try up to 5 calls

        for (int i = 0; i < 5; ++i) {
            // Create the observer
            MyResponseObserver observer = new MyResponseObserver();

            // Call the service
            service.getDetails(supplyRequest(), observer);

            try {
                // Wait for the result
                Boolean result = observer.completable.get();

                // Or wait with a timeout
                // observer.completable.get(30, TimeUnit.SECONDS);

                // Completed successfully
                isCompleted = true;
                return;
            } catch (ExecutionException e) {
                // Completed with exception. Retry.
            } catch (InterruptedException e) {
                return;
            }
        }
    }

    /** Response callback handler */
    private static class MyResponseObserver implements ResponseObserver {
        /** Result object (change Boolean to the type of your result) */
        public final CompletableFuture<Boolean> completable = new CompletableFuture<>();

        @Override
        public void onException() {
            // Signal an error
            completable.completeExceptionally(new Exception("Error"));
        }

        @Override
        public void onCompletion() {
            // Signal a result
            completable.complete(true);
        }

        @Override
        public void onProcessing() {
        }
    }
}

答案 1 :(得分:1)

可能是CountDownLatch的某种组合。尝试关注

public class CallThread implements Runnable {
    private final CountDownLatch completionLatch = new CountDownLatch(1);

    public void run(){
        callService();

        //Wait without timeout, bad idea
        try {
            completionLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void callService() {
        //Service is the object that calls the service
        Service service = getService();
        //Request object is populated
        ResponseObserver response = new MyResponseObserver(completionLatch);
        Request request = supplyRequest();
        service.getDetails(request, response);
    }

    class MyResponseObserver {
        private CountDownLatch completionLatch;

        MyResponseObserver(CountDownLatch latch) {
            this.completionLatch = latch;
        }

        public void onException(){
            /* Retry on exception */
            callService();
        }
        public void onCompletion(){
            completionLatch.countDown();
            //process the result
        }
        public void onProcessing(){
            //This could be called multiple time
        }
    };
}

此外,您可能还可以考虑使用Callable而不是Runnable,因为main正在等待处理,可能最好在主线程本身中执行。下面是它的外观

public CallThread implements Callable<MyResult> {
    private MyResult myResult;
    private final CountDownLatch completionLatch = new CountDownLatch(1);

    public MyResult call(){
        callService();

        //Wait without timeout, bad idea
        try {
            completionLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return myResult;
    }

    public setMyResult(MyResult myResult) {
        this.myResult = myResult;
    }

    public void callService() {
        //Service is the object that calls the service
        Service service = getService();
        //Request object is populated
        ResponseObserver response = new MyResponseObserver(completionLatch);
        Request request = supplyRequest();
        service.getDetails(request, response);
    }

    class MyResponseObserver {
        private CountDownLatch completionLatch;

        MyResponseObserver(CountDownLatch latch) {
            this.completionLatch = latch;
        }

        public void onException(){
            /* Retry on exception */
            callService();
        }
        public void onCompletion(){
            completionLatch.countDown();
            //process the result
            setMyResult(result);

        }
        public void onProcessing(){
            //This could be called multiple time
        }
    };
}

在main()

...
FutureTask task = new FutureTask(new CallThead());
new Thread(task).start();

MyResult result = task.get();//blocks thead