我认为我对Threads有点迷茫,因为我不明白为什么它不起作用...
我有一个包含服务器客户端和节点的程序。 客户端将分组数据(GroupedDataFrame)发送到服务器,要求计算例如平均。服务器将该任务分配给其节点,节点将对其进行计算并将其结果返回给服务器。
我的问题是,当我使用applyWithThreads时,NODE返回一个空的DataFrame (没有计算结果)(如果我使用普通的“ apply”(没有线程),那么它工作正常 >)。
据我所知,创建NodeResult的命令不会等待上一个函数完成,即applywithThreads ,因此,它会发送空的DF(因为如果我设置了等待时间,例如2秒它的工作:/,或者如果我使用此注释循环,但我知道这是不好的做法)
我想以某种方式解决它!如何等待applythread完成(将形成returnToServer)?
class ListenFromServer extends Thread {
public void run() {
while (true) {
try {
Object obj = sInput.readObject();
if (obj instanceof String) {
display((String) obj);
} else if (obj instanceof NodeRequestGDF) {
display("I have received NodeRequest from client ID: " + ((NodeRequestGDF) obj).getClientID());
// DataFrame returnToServer = (((NodeRequestGDF) obj).groupedDF.apply(((NodeRequestGDF) obj).getFunction()));
DataFrame returnToServer = (((NodeRequestGDF) obj).groupedDF.applywithThreads(((NodeRequestGDF) obj).getFunction()));
// while (returnToServer.size() != (((NodeRequestGDF) obj).getGroupedDF().getSize()));
NodeResultDF nodeResultDF = new NodeResultDF(returnToServer, ((NodeRequestGDF) obj).getClientID());
sendToServer(nodeResultDF);
display("I have returned result to Server to client ID: " + nodeResultDF.clientID);
} else {
display("I have received something i do not know what is this :(");
}
} catch (IOException e) {
display("Server has close the connection: " + e);
} catch (ClassNotFoundException e2) {
e2.printStackTrace();
}
}
}
}
这是applyWithThreads的代码:
public DataFrame applyWithThreads(Applyable fun) {
DataFrame ret = new DataFrame();
ArrayList<DataFrameThread> threadList = new ArrayList<>();
for (DataFrame df : this.data) {
DataFrameThread tmp = new DataFrameThread(df, fun, ret);
threadList.add(tmp);
}
ExecutorService threadPool = Executors.newFixedThreadPool(MAX_Threads);
for (DataFrameThread th : threadList) {
threadPool.execute(th);
}
threadPool.shutdown();
return ret;
}
和DataFrameThread的代码:
import GroupFunctions.Applyable;
public class DataFrameThread extends Thread {
DataFrame ret;
DataFrame DF;
Applyable fun;
public DataFrameThread(DataFrame df, Applyable fun, DataFrame ret) {
this.DF = df;
this.fun = fun;
this.ret = ret;
}
@Override
public void run() {
DataFrame d = null;
try {
d = fun.apply(DF);
} catch (InconsistentTypeException e) {
e.printStackTrace();
}
synchronized (ret) {
ret.addAnotherDF(d);
}
}
}
``
答案 0 :(得分:1)
您的代码有很多问题。我会尝试越过它们。
关键的:
DataFrameThread
扩展了Thread
,但是,如果您像使用ExecutorService那样使用线程池,则不再由您创建线程。不用说extends Thread
,而是说implements Runnable
。shutdown()
不会等待它停止。您可以在致电awaitTermination
之后致电shutdown
,但这不是您应该使用ExecutorService的方式。submit
而不是execute
。 submit
返回Future<?>
,您可以在get()
上调用Future
,它将阻塞直到完成。Runnable
,而实现Callable
。 Callable
用于返回值的任务。您无需从ret.addAnotherDF
中调用Runnable
,而是从可调用对象返回DataFrame。然后,submit
将返回一个Future<DataFrame>
,并且当您在其上调用get
时,它会在线程完成后返回DataFrame对象。get
时调用Future
上的ExecutorService
,而不是在每个任务之后都进行调用(如果您在每个任务之后都执行,则不会再并行化问题)重要:
applyWithThreads
调用创建一个新的ExecutorService。线程池的关键是尽可能长时间地保持线程池,因为创建线程是一项昂贵的操作。这就是为什么您不应该使用shutdown
和awaitTermination
来确定任务何时完成的原因;这就是为什么您可以使用Future
个对象这样做的原因。