如何使用ScheduledExecutorService返回值?

7
我使用ScheduledExecutorService,希望它每10秒进行一次计算,持续一分钟,在那一分钟结束后,将新值返回给我。如何实现?
例如:如果它接收到数字5,它会增加+1六次,然后在一分钟后返回值11。
目前我的代码如下,但无法正常工作:
package com.example.TaxiCabs;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import static java.util.concurrent.TimeUnit.*;


public class WorkingWithTimeActivity {
public int myNr;
public WorkingWithTimeActivity(int nr){
    myNr = nr;
}
private final ScheduledExecutorService scheduler =
        Executors.newScheduledThreadPool(1);

public int doMathForAMinute() {
    final Runnable math = new Runnable() {
        public void run() {
            myNr++;
        }
    };
    final ScheduledFuture<?> mathHandle =
            scheduler.scheduleAtFixedRate(math, 10, 10, SECONDS);
    scheduler.schedule(
            new Runnable() {
                public void run() {
                    mathHandle.cancel(true);
                }
            }, 60, SECONDS);
    return myNr;
}

在我的主活动中,我希望在1分钟后将txtview文本更改为11。

WorkingWithTimeActivity test = new WorkingWithTimeActivity(5);
txtview.setText(String.valueOf(test.doMathForAMinute()));

是的,我正在Android上使用它。 - nairdat
2个回答

9

您应该使用Callable而不是Runnable,因为它可以返回值。

Callable接口与Runnable类似,都是为了那些实例有可能被其他线程执行的类而设计的。然而,Runnable不返回任何结果,也不能抛出已检查的异常。

public class ScheduledPrinter implements Callable<String> {
    public String call() throws Exception {
        return "somethhing";
    }
}

然后像下面这样使用它。
    ScheduledExecutorService scheduler = Executors
            .newScheduledThreadPool(1);
    ScheduledFuture<String> future = scheduler.schedule(
            new ScheduledPrinter(), 10, TimeUnit.SECONDS);
    System.out.println(future.get());

这是一次性的计划,因此它只会执行一次,一旦get调用返回,您需要再次安排它。


然而,在您的情况下,使用简单的AtomicInteger并调用addAndGet将更容易,一旦满足条件,通过调用cancel取消调度。


@nairdat Callable被设计为特殊用途,用于返回值并抛出异常。 - Amit Deshpande
当AtomicInteger增长到其最大大小时会发生什么? - newday
我不理解这个示例。你使用10秒的时间间隔启动调度程序,但是接着你又说它是一次性执行,需要自己重新启动? - html_programmer

0

如果你想从doMathForAMinute返回结果,那么根本不需要使用ScheduledExecutorService。只需创建一个循环来运行计算,然后Thread.sleep()。使用ScheduledExecutorService的整个思路是为了释放启动任务的线程,使其不必等待结果,但在这里你并不需要释放它。

如果像我怀疑的那样,调用doMathForAMinute的线程是GUI线程,那么这是完全错误的,因为你的GUI会卡住一分钟而无法响应。相反,doMathForAMinute应该只启动并行计算,而并行任务应该使用runOnUiThread或其他方式自行更新UI。

另请参阅:

Android:runOnUiThread并不总是选择正确的线程?

我应该在哪里创建和使用ScheduledThreadPoolExecutor、TimerTask或Handler?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接