0

use thread pool:

ExecutorService exec = Executors.newFixedThreadPool(5);
FutureTask<Integer> ft = new FutureTask<Integer>(() -> rpcMethod());
exec.submit(ft);

call run method:

FutureTask<Integer> ft = new FutureTask<Integer>(() -> rpcMethod());
ft.run()

I looked at the run method source code, as if it was a synchronous call, it seems that there is no new thread. The reason I have this problem is because I looked at the source code of Dubbo's RpcContext#asyncCall and found that it is directly using FutureTask#run.Here is some part of the code.

public <T> Future<T> asyncCall(Callable<T> callable) {
        try {
            try {
                setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
                final T o = callable.call();
                //local调用会直接返回结果.
                if (o != null) {
                    FutureTask<T> f = new FutureTask<T>(new Callable<T>() {
                        public T call() throws Exception {
                            return o;
                        }
                    });
                    f.run();
                    return f;
                } else {

                }
zzkyeee
  • 65
  • 6
  • 3
    Yes, that's the difference. Calling `run()` makes it a synchonous code. That's the trivial syncronous executor service implementation. – M. Prokhorov Oct 29 '19 at 10:00
  • Right. When you call `run` there is no new thread. It is just a task. A task is just some code which can be run and return a result. The executor is what schedules that task for execution on one or more threads. – Michael Oct 29 '19 at 10:00
  • `ft.run()` just calls the run `method`, nothing else. `FutureTask` is just a regular interface. – f1sh Oct 29 '19 at 10:03
  • I modified the original question, please have a look. – zzkyeee Oct 29 '19 at 10:41
  • @zzkyeee have answered it, please have a look. – Vinay Prajapati Oct 29 '19 at 10:51

1 Answers1

1

FutureTask is a implementation of Runnable.

the difference is

if you use exec.submit(ft); its async, executed in two different threads.

if you use ft.run(); its been executed in the same thread.

If there are any doubts, try this. I put getResult() in another method, so you have a more explicit call stack:

public class FutureExample {

private Callable<Long> call = new Callable<Long>() {

    private Long getResult(){
        return Thread.currentThread().getId();
    }

    @Override
    public Long call() {
        return getResult();
    }
};

private Long callByRun() throws ExecutionException, InterruptedException {
    FutureTask<Long> ft = new FutureTask<>(call);
    ft.run();
    return ft.get();
}

private Long callByExec() throws ExecutionException, InterruptedException {
    ExecutorService pool = Executors.newFixedThreadPool(5);
    FutureTask<Long> ft = new FutureTask<>(call);
    pool.submit(ft);
    Long result = ft.get();
    pool.shutdown();
    return result;
}

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Long mainThreadId = Thread.currentThread().getId();
    System.out.println(String.format("main: %d callByRun %d", mainThreadId, new FutureExample().callByRun()));
    System.out.println(String.format("main: %d callByExec %d", mainThreadId, new FutureExample().callByExec()));
}

}

Curiosa Globunznik
  • 3,129
  • 1
  • 16
  • 24
JeryZhi
  • 13
  • 2