Java ScheduledFuture 获取列表

标签 java multithreading scheduling futuretask

此代码总是返回 10。我认为接收所有功能列表存在问题。我需要解析每个功能,并在变量限制等于 5 时停止执行调度程序。我该怎么做?

static int limit = 0;
static final int testNum = 10;

static ScheduledExecutorService scheduler;
public static void main(String[] args) {
    scheduler = Executors
            .newScheduledThreadPool(5);
    ScheduledFuture<Integer> future = scheduler.schedule(new ScheduledPrinter(), 10, TimeUnit.SECONDS);
    try {
        while (true) {
            System.out.println(future.get());
            if(future.get() != testNum){
                return;
            }
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}
private static class ScheduledPrinter implements Callable<Integer> {
    public Integer call() throws Exception {
        limit++;
        if(limit==5) {
            scheduler.shutdown();
            return limit;
        }
        return testNum;
    }
}

最佳答案

让我们看看这里发生了什么。 scheduler.schedule(new ScheduledPrinter(), 10, TimeUnit.SECONDS) 仅运行 ScheduledPrinter.call() 一次。 Here是 API 文档。

你想要的可能是 scheduleAtFixedRate 。这需要一个 Runnable 而不是可调用,因此代码将如下所示:

static volatile int limit = 0; // make it volatile because of *possible* multithreaded access
                               // an AtomicInteger would do too
static final int testNum = 10;

static ScheduledExecutorService scheduler;

public static void main(String[] args) {
    scheduler = Executors
            .newScheduledThreadPool(5);
    // discarding the future. No need to use it here.
    ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(new ScheduledPrinter(), 10L, 10L, TimeUnit.SECONDS);
}

/** Printing and counting happens here **/
private static class ScheduledPrinter implements Runnable {

    @Override
    public void run() {
        limit++;
        if(limit==5) {
            scheduler.shutdown();
            printNum(limit);
        } else {
            printNum(testNum);
        }
    }

    private void printNum(int num) {
        System.out.println(num);
    }
}

更新

OP询问如何从Runnable.run()方法返回值?不幸的是,这是不可能的。我们必须在定期运行和返回值之间进行选择,因为 ScheduledExecutorService 无法同时执行两者。

仍然可以从Runnable中获取值。我们必须为此分享一个引用。这是一个基本方法:

    final Queue<Integer> numsPrinted = new ConcurrentLinkedQueue<>(); // a concurrent collection
    ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay( // using scheduleWithFixedDelay because probably this is what you want
            new ScheduledPrinter(numsPrinted), // passing the reference
            10L, 10L, TimeUnit.SECONDS);
    try {
        future.isDone();
        Object obj = future.get(80, TimeUnit.SECONDS); // blocks until 80 secs or until the task is done
        System.out.println(obj);
        System.out.println(Arrays.toString(numsPrinted.toArray()));
    } catch (TimeoutException e) {
        System.out.println(Arrays.toString(numsPrinted.toArray()));
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    } 

ScheduledPrinter 现在看起来像这样:

private static class ScheduledPrinter implements Runnable {

    private final Queue<Integer> numsPrinted;

    public ScheduledPrinter(Queue<Integer> numsPrinted) {
        this.numsPrinted = numsPrinted; // storing the reference
    }

    @Override
    public void run() {
        limit++;
        if(limit==5) {
            //scheduler.awaitTermination(timeout, unit)
            scheduler.shutdown();
            storeAndPrintNum(limit);
        } else {
            storeAndPrintNum(testNum);
        }
    }

    private void storeAndPrintNum(int num) {
        numsPrinted.add(num); // using the reference
        System.out.println(num);
    }
}

关于Java ScheduledFuture 获取列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48222592/

相关文章:

c# - C# 中的 Mutex - 从未同步的代码块同步

C# 任务线程池 - 仅在 10 个线程中运行 100 个任务

java - tomcat多线程问题

java - 无法执行目标org.apache.hadoop:hadoop-maven-plugins:2.4.2-SNAPSHOT:protoc

language-agnostic - 是否存在不希望优先继承的情况?

php - php上的休眠功能

java - 加载扩展时出错无法从 'C:\..\Local\Temp\scoped_dir6312_32763\internal' 加载扩展。禁止加载解压缩的扩展

java - 如何手动将项目添加到另一个项目的构建路径?

Java 拆分大写字符串并将其全部转换为小写

java - 如何使用 Apache 文件上传启用附件