我是多线程编程的新手。使用join方法时出现意外行为。有时两个线程都给出相同的结果,有时只显示一个结果,有时显示正确的结果。我做错了什么?
public class Client {
public static void main(String args[]) throws Exception {
String model = args[0];
String property = args[1];
String parameters = args[2];
String wsdlPaths = args[3];
int numServices = Integer.parseInt(args[4]);
String[] parameter;
getParameters(parameters, parameter);
String[] wsdl;
getWSDL(wsdlPaths, wsdl);
Thread[] t = new Thread[numServices];
ClientHelper[] nch = new ClientHelper[numServices];
TestStub[] stub = new TestStub[numServices];
TestStub.Experiment[] request = new TestStub.Experiment[numServices];
TestStub.ExperimentResponse[] response = new TestStub.ExperimentResponse[numServices];
for (int i = 0; i < numServices; i++) {
stub[i] = new TestStub(wsdl[i]);
request[i] = new TestStub.Experiment();
request[i].setArgs0(model);
request[i].setArgs1(property);
request[i].setArgs2(parameter[i]);
nch[i] = new ClientHelper(stub[i], request[i]);
t[i] = new Thread(nch[i]);
t[i].start(); // When I moved this statement to the next loop just before the join method, the program behaved like a single threaded program and was working correctly.
}
for (int i = 0; i < numServices; i++) {
try {
t[i].join();
} catch (InterruptedException e) {
}
System.out.println(t[i].getName());
response[i] = nch[i].response;
System.out.println("Response " + i + " : " + response[i].get_return());
}
}
}
public class ClientHelper implements Runnable {
TestStub stub;
TestStub.Experiment request;
TestStub.ExperimentResponse response;
public ClientHelper(TestStub stub, TestStub.Experiment request){
this.stub = stub;
this.request = request;
}
public void run() {
try {
response = stub.Experiment(request);
}
catch (Exception e) {
}
}
}
答案 0 :(得分:0)
由于发布的代码无法编译,而且可能只是太大而无法推断出根本原因,我会抓住机会并暗示可能出现的问题。
您的代码包含两个for循环:
for (int i = 0; i < numServices; i++) {
...
t[i].start();
}
for (int i = 0; i < numServices; i++) {
t[i].join();
...
}
您的观察推断出
for (int i = 0; i < numServices; i++) {
t[i].start();
t[i].join();
...
}
不会导致问题。
嗯,那是因为您现在正在序列化该进程,并且根本没有并发执行。我可以从中推断出的唯一一点就是你在线程之间共享状态,可能在Runnable的构造函数的TestStub
或TestStub.Experiment
参数中。除非有代码要执行,否则我无法说明共享内容,但这肯定是原因。
<强>更新强>
在考虑语句stub.Experiment(request);
之后,我还建议验证(生成的)Web服务代理和Web服务客户端框架是否也是线程安全的。它们可能是发布可能跨线程使用的对象引用,因此需要使用适当的锁进行显式同步。遗憾的是,没有简单的方法来确定库和一组生成的类是否是线程安全的。
答案 1 :(得分:0)
您的所有请求都使用相同的型号和属性。如果他们有某种状态 - 你会得到这种行为。
request[i].setArgs0(model);
request[i].setArgs1(property);
答案 2 :(得分:0)
t[i].join();
这不符合你的想法!它“暂停”主要方法!它让主要方法等待t [i]完成。之后,main方法恢复该循环。
答案 3 :(得分:0)
不是直接使用Threads,通常最好使用像ExecutorService这样的线程池。
final String[] parameter= getParameters(parameters);
final String[] wsdl = getWSDL(wsdlPaths);
ExecutorService executor = Executors.newCachedThreadPool();
List<Future<TestStub.ExperimentResponse>> futures = new ArrayList<Future<TestStub.ExperimentResponse>>();
for (int j = 0; j < numServices; j++) {
final int i = j;
futures.add(executor.submit(new Callable<TestStub.ExperimentResponse>() {
@Override
public TestStub.ExperimentResponse call() throws Exception {
TestStub stub = new TestStub(wsdl[i]);
TestStub.Experiment request = new TestStub.Experiment();
request.setArgs0(model);
request.setArgs1(property);
request.setArgs2(parameter[i]);
return stub.Experiment(request);
}
}));
}
for (Future<ExperimentResponse> future : futures) {
TestStub.ExperimentResponse response = future.get();
System.out.println("Response: " + response.get_return());
}
executor.shutdown();