假设以下说明性示例。 B类涉及一些数值程序,例如阶乘。计算在一个单独的线程中运行:
public class B implements Callable <Integer> {
private int n;
public B(int n_) {n = n_;}
public Integer call() {return f();}
public Integer f() {
if (n == 1) return 1;
else {
int fn = 1;
for (int i = n; i > 1; i--) fn *= i;
return fn;
}
}
}
下一个A类使用阶乘来评估余数r = x ^ n / n!
public class A {
public double rem (double x, int n){
B b = new B(n);
ExecutorService es = Executors.newFixedThreadPool(5);
Future <Integer> nf = es.submit(b); //Factorial
es.submit(()->
{
double r = 1; //Remainder x^n/n
for (int i = 1; i <= n; i++) r = r * x;
try { r = r / nf.get();}
catch (Exception e) {e.printStackTrace();}
return r;
});
return 0;
}
}
如何确保rem()函数在submit()过程完成后返回值?不幸的是,这不起作用:
public static void main(String[] args) {
A a = new A();
double r = a.rem(0.5, 10);
}
是否有必要在另一个线程中运行A并修改A以便:
public class A implements Callable <Double> {
private int n;
private double x;
public A(double x_, int n_) {x = x_; n = n_;}
public Double call() {return rem(x, n);}
....
}
并在一个单独的线程中运行A.rem()?
public static void main(String[] args) {
A a = new A(0.5, 10);
ExecutorService es = Executors.newFixedThreadPool(5);
Future <Double> nf = es.submit(a); //Factorial
double r = nf.get();
}
有没有更简单的解决方案避免两个不同的线程?
我可以要一个简短的示例代码吗?
感谢您的帮助......
答案 0 :(得分:2)
在提交给线程池的任务中使用Future.get()
是危险的:当前线程被阻止,无法运行其他任务。这可能导致线程饥饿 - 一种特定的死锁。
正确的方法是制作非循环图,其中每个节点都是CompletableFuture
类型的异步函数调用,它只在计算完所有参数后运行。只使用在主线程上调用的Future.get()
提取一般结果。
这是一个这样的图表的示例,接近您想要实现的内容:首先,函数factorial和power并行运行。一旦它们都完成,就会调用计算提醒函数。
public static long fact(int n) {
long res = 1;
for (int i = n; i > 1; i--) res *= i;
return res;
}
public static double pow(double base, int pow) {
double r = 1;
for (int i = 0; i < pow; i++) r *= base;
return r;
}
public static double rem(double val1, long val2) {
return val1/val2;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(5);
double base = 0.5;
int n = 10;
CompletableFuture<Double> f1 = CompletableFuture.supplyAsync(() -> pow(base, n), es);
CompletableFuture<Long> f2 = CompletableFuture.supplyAsync(() -> fact(n), es);
CompletableFuture<Double> f3 = f1.thenCombineAsync(f2, (v1,v2)->rem(v1,v2), es);
double r1 = f3.get();
System.out.println("r1="+r1);
// compare with the result of synchronous execution:
double r2 = rem(pow(base, n), fact(n));
System.out.println("r2="+r2);
}
答案 1 :(得分:0)
可调用对象实现方法get,返回线程计算的值 - 看看以下链接: https://blogs.oracle.com/corejavatechtips/using-callable-to-return-results-from-runnables 欢呼声,
大卫