番石榴中的 ListenableFuture 将在哪个线程中调用 FutureCallback?
In which thread FutureCallback will be called for a ListenableFuture in Guava?
我一定是漏掉了什么。我很难理解将在哪个线程中为 Guava 中的 ListenableFuture 调用 FutureCallback。
我的代码的第一个版本是:
Log.d("mydebug", "Before submit, " + Thread.currentThread() + ", " + android.os.Process.myTid());
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture future = service.submit(new Runnable() {
@Override
public void run() {
Log.d("mydebug", "In run, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
});
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(Object result) {
Log.d("mydebug", "In onSuccess, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
@Override
public void onFailure(Throwable thrown) {
Log.d("mydebug", "In onFailure, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
}, MoreExecutors.sameThreadExecutor());
我的代码的第一个版本的输出是:
02-04 12:37:00.815 11327 11327 D mydebug : Before submit, Thread[main,5,main], 11327
02-04 12:37:00.825 11327 11382 D mydebug : In run, Thread[pool-1-thread-1,5,main], 11382
02-04 12:37:00.825 11327 11327 D mydebug : In onSuccess, Thread[main,5,main], 11327
我将 Thread.sleep 添加到 Runnable 中以制作我的代码的第二个版本:
Log.d("mydebug", "Before submit, " + Thread.currentThread() + ", " + android.os.Process.myTid());
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture future = service.submit(new Runnable() {
@Override
public void run() {
Log.d("mydebug", "In run, " + Thread.currentThread() + ", " + android.os.Process.myTid());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(Object result) {
Log.d("mydebug", "In onSuccess, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
@Override
public void onFailure(Throwable thrown) {
Log.d("mydebug", "In onFailure, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
}, MoreExecutors.sameThreadExecutor());
第二版代码的输出是:
02-04 12:43:02.165 17180 17180 D mydebug : Before submit, Thread[main,5,main], 17180
02-04 12:43:02.205 17180 17229 D mydebug : In run, Thread[pool-1-thread-1,5,main], 17229
02-04 12:43:04.215 17180 17229 D mydebug : In onSuccess, Thread[pool-1-thread-1,5,main], 17229
所以在我的第一版代码中,FutureCallback是在调用service.submit的线程中执行的,而我的第二版代码是在线程池中的一个线程中执行FutureCallback的。我很迷惑。 MoreExecutors.sameThreadExecutor() 到底是什么意思?它没有像我预期的那样工作。
此处的文档非常明确:
Note: If the callback is slow or heavyweight, consider supplying an executor. If you do not supply an executor, addCallback will use a direct executor [note: this is equivalent to sameThreadExecutor()
which you passed in explicitly], which carries some caveats for heavier operations. For example, the callback may run on an unpredictable or undesirable thread:
If the input Future is done at the time addCallback is called, addCallback will execute the callback inline. [that is, directly in the call to addCallback
on the same thread where addCallback
was called]
If the input Future is not yet done, addCallback will schedule the callback to be run by the thread that completes the input Future, which may be an internal system thread such as an RPC network thread.
请注意,"direct executor" 是执行程序的最简单可能实现:
final class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
我一定是漏掉了什么。我很难理解将在哪个线程中为 Guava 中的 ListenableFuture 调用 FutureCallback。
我的代码的第一个版本是:
Log.d("mydebug", "Before submit, " + Thread.currentThread() + ", " + android.os.Process.myTid());
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture future = service.submit(new Runnable() {
@Override
public void run() {
Log.d("mydebug", "In run, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
});
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(Object result) {
Log.d("mydebug", "In onSuccess, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
@Override
public void onFailure(Throwable thrown) {
Log.d("mydebug", "In onFailure, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
}, MoreExecutors.sameThreadExecutor());
我的代码的第一个版本的输出是:
02-04 12:37:00.815 11327 11327 D mydebug : Before submit, Thread[main,5,main], 11327
02-04 12:37:00.825 11327 11382 D mydebug : In run, Thread[pool-1-thread-1,5,main], 11382
02-04 12:37:00.825 11327 11327 D mydebug : In onSuccess, Thread[main,5,main], 11327
我将 Thread.sleep 添加到 Runnable 中以制作我的代码的第二个版本:
Log.d("mydebug", "Before submit, " + Thread.currentThread() + ", " + android.os.Process.myTid());
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture future = service.submit(new Runnable() {
@Override
public void run() {
Log.d("mydebug", "In run, " + Thread.currentThread() + ", " + android.os.Process.myTid());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(Object result) {
Log.d("mydebug", "In onSuccess, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
@Override
public void onFailure(Throwable thrown) {
Log.d("mydebug", "In onFailure, " + Thread.currentThread() + ", " + android.os.Process.myTid());
}
}, MoreExecutors.sameThreadExecutor());
第二版代码的输出是:
02-04 12:43:02.165 17180 17180 D mydebug : Before submit, Thread[main,5,main], 17180
02-04 12:43:02.205 17180 17229 D mydebug : In run, Thread[pool-1-thread-1,5,main], 17229
02-04 12:43:04.215 17180 17229 D mydebug : In onSuccess, Thread[pool-1-thread-1,5,main], 17229
所以在我的第一版代码中,FutureCallback是在调用service.submit的线程中执行的,而我的第二版代码是在线程池中的一个线程中执行FutureCallback的。我很迷惑。 MoreExecutors.sameThreadExecutor() 到底是什么意思?它没有像我预期的那样工作。
此处的文档非常明确:
Note: If the callback is slow or heavyweight, consider supplying an executor. If you do not supply an executor, addCallback will use a direct executor [note: this is equivalent to
sameThreadExecutor()
which you passed in explicitly], which carries some caveats for heavier operations. For example, the callback may run on an unpredictable or undesirable thread:
If the input Future is done at the time addCallback is called, addCallback will execute the callback inline. [that is, directly in the call to
addCallback
on the same thread whereaddCallback
was called]If the input Future is not yet done, addCallback will schedule the callback to be run by the thread that completes the input Future, which may be an internal system thread such as an RPC network thread.
请注意,"direct executor" 是执行程序的最简单可能实现:
final class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}