【问题标题】:How FutureTask is asynchronous computationFutureTask 是如何进行异步计算的
【发布时间】:2013-11-04 13:18:43
【问题描述】:
new Thread(new Runnable() {
           public void run() {
                 .............
                 .............
                 .............
    }
}).start();

如果我在 main 中执行此操作,它将创建一个新线程并向其提交一个任务以进行异步计算。

如果您看到 FutureTask documentation 它还会显示:

可取消的异步计算。这个类提供了一个基础 Future 的实现,带有启动和取消的方法 计算,查询计算是否完成,并检索 计算结果。

那么FutureTask是一个asynchronous computation是如何在内部创建线程并提交我们在实例化FutureTask时给它的任务,例如:

FutureTask f = new FutureTask(new MyCallable());

否则它不能是异步计算,请提供来自FutureTasksource code的代码sn-p,它将任务提交给线程,使其异步计算。谢谢。


我得到了答案。它基本上是试图在与调用者相同的线程中运行任务。在给定的代码中非常明显:

当您调用futureTask.run() 时,它只会调用sync.innerRun();,而sync 是内部类Sync 的实例。因为它只是在同一线程中的可调用对象上调用call()

void innerRun() {
        if (!compareAndSetState(READY, RUNNING))
            return;

        runner = Thread.currentThread(); //here it is getting the current thread
        if (getState() == RUNNING) { 
            V result;
            try {
                result = callable.call();//here calling call which executes in the caller thread.
            } catch (Throwable ex) {
                setException(ex);
                return;
            }
            set(result);
        } else {
            releaseShared(0); // cancel
        }
    }

【问题讨论】:

  • FutureTask<V> implements RunnableFuture<V>,它本身就是一个Runnable

标签: java multithreading asynchronous futuretask


【解决方案1】:

那么,FutureTask 是一个异步计算,它在内部创建线程并提交我们在实例化 FutureTask 时给它的任务,例如:

FutureTask 不是为用户直接使用而设计的。它旨在通过ExecutorService 接口和实现它的类来使用。正是那些使用FutureTask 并派生线程等的类。您可能需要阅读有关how to use the ExecutorService concurrency classes 的更多信息。

ThreadPoolExecutor 类是实际管理池中线程的主要类。通常你调用Executors.newCachedThreadPool()Executors.newFixedThreadPool(10) 来获取它的一个实例。

// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
// define your jobs somehow
for (MyCallable job : jobsToDo) {
    // under the covers this creates a FutureTask instance
    Future future = threadPool.submit(job);
    // save the future if necessary in a collection or something
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
// now we can go back and call `future.get()` to get the results from our jobs

从学术的角度来看,在 TPE 内部扩展了 AbstractExecutorService,在那里您可以看到 FutureTask 类用于管理线程池中的任务:

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}
...
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

TPE 内部的代码相当复杂,显示执行异步调用的“sn-p”并不容易。 TPE 查看是否需要向池中添加更多线程。将它提交到一个可以拒绝或接受它的任务队列,然后线程将任务出列并在后台运行它们。

【讨论】:

  • 有时我们也会这样做futureTask.run() 它不是异步任务计算还是只是在最终调用者的同一线程上运行?
  • FutureTask.run() 只是调用您的任务的 run() 方法并带有一些锁定。它不会派生任何线程@Trying。你不应该直接调用它。
  • 正确@Trying。它只是在同一个线程中直接调用它。查看FutureTask的来源。
  • 你应该阅读ExecutorService类@Trying:docs.oracle.com/javase/tutorial/essential/concurrency/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多