[英]Replacing busy loop and sleep in thread
I have a Thread that calls a certain service. 我有一个调用特定服务的线程。 The service defines a callback function that can be called multiple times as long as there is data onProcessing(). 该服务定义了一个回调函数,只要有onProcessing()数据,就可以多次调用该回调函数。
The onCompletion() is called once it is finished. 一旦完成,就会调用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);
}
}
}
I have created a busy loop that checks for the isCompleted and having it sleep. 我创建了一个忙循环,用于检查isCompleted并使其处于睡眠状态。 What I am doing now..is to use sleep command to be able for the function to be completed until issuing a next request. 我现在正在执行的操作是使用sleep命令使该功能能够完成,直到发出下一个请求。
I am not sure if this is optimal as sometimes..it does not take 10 seconds before onCompletion() is called. 我不确定这是否是最佳选择,因为有时..调用onCompletion()不需要10秒钟。 I just wanted the service to return something before I could issue another request. 我只是想让服务返回某些内容,然后再发出另一个请求。
Is there a way to optimized my code? 有没有一种方法可以优化我的代码?
A CountDownLatch
or CompletableFuture
can be used to wait for a condition asynchronously: CountDownLatch
或CompletableFuture
可用于异步等待条件:
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() {
}
}
}
It's probably going to be some combination of CountDownLatch
. 可能是CountDownLatch
某种组合。 Try following 尝试跟随
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
}
};
}
Besides that you can probably also consider using Callable
instead of Runnable
since main
is waiting for the processing, probably its better to do in main thread itself. 除此之外,您还可以考虑使用Callable
而不是Runnable
因为main
正在等待处理,可能最好在main线程本身中执行。 Below is a what it would look like 以下是它的外观
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
}
};
}
in main() 在main()中
...
FutureTask task = new FutureTask(new CallThead());
new Thread(task).start();
MyResult result = task.get();//blocks thead
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.