我正在尝试学习java并发API,对于我的练习,我想安排一个作业每隔X秒定期运行一次。该作业将计算一个随机数。
我想在完成后立即获得计划任务的结果。 我无法仅通过API完成此操作,因此我将其破解。
有没有办法在不使用低级机制的情况下更好地做到这一点?
我希望能够删除MyRandomGiverTask.getResult()
中的同步,而是使用
像ScheduledFuture.get()
之类的东西。但在我的代码中,ScheduledFuture永远不会完成/完成。
这是我目前的解决方案:
class A {
public static void main() {
MyRandomGiverTask task = new MyRandomGiverTask(200);
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
ScheduledFuture<Double> scheduledDouble =
(ScheduledFuture<Double>) scheduler
.scheduleAtFixedRate(task, 1, 4, TimeUnit.SECONDS);
while (true) {
System.out.println(" >> " + task.getResult());
}
}
public class MyRandomGiverTask implements Runnable {
MyRandomGiver giver = new MyRandomGiver();
int param;
double result;
public MyRandomGiverTask(int param) { this.param = param; }
@Override public void run() { result = giver.getRandom(param); }
public double getResult() {
try {
while (result == 0d) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result;
} finally {
result = 0d;
}
}
}
}
答案 0 :(得分:7)
您的任务按固定费率安排。这意味着在您取消任务之前,执行者将以固定费率一次又一次地执行该任务。这样的任务唯一能做的就是产生副作用。它不能返回任何内容,因为执行程序返回的未来代表任务的所有待处理执行。顺便说一句,您会注意到schedule
方法将Callable作为参数(可能会产生某些结果),而sceduleAtFixedRate
方法只接受Runnable作为参数(返回void,因此无法返回任何东西)。
因此,如果要打印每次执行的结果,那么只需让任务本身(Runnable)打印其结果,或让runnable将其结果放入阻塞队列,并使主线程{{1从队列中。因此主线程将被阻塞,一些结果被放入队列中。
答案 1 :(得分:2)
如果要计算每个随机数,请使用BlockingQueue。计划任务put()
队列中的新随机数以及他们想要的任何内容take()
。
另外,如果 要使用类似您的解决方案的内容,您可能希望使用wait()
/ notify()
,而不是sleep()
。