Java ScheduledFuture 获取列表
Java ScheduledFuture get List
此代码总是 returns 我 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;
}
}
方法 ScheduledPrinter.call() 只被调用一次,在 while 循环中,您总是 return 计算一次的值。因此 limit 永远不会增加,也永远不会调用 shutdown。所以我认为您需要更改逻辑,也许 运行 更多线程。
让我们看看这里发生了什么。 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()
方法中获取 return 值?不幸的是,这是不可能的。我们必须在周期性 运行 和 return 值之间做出选择,因为 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);
}
}
此代码总是 returns 我 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;
}
}
方法 ScheduledPrinter.call() 只被调用一次,在 while 循环中,您总是 return 计算一次的值。因此 limit 永远不会增加,也永远不会调用 shutdown。所以我认为您需要更改逻辑,也许 运行 更多线程。
让我们看看这里发生了什么。 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()
方法中获取 return 值?不幸的是,这是不可能的。我们必须在周期性 运行 和 return 值之间做出选择,因为 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);
}
}