[英]Using Thread.join() method
我是多線程編程的新手。 使用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) {
}
}
}
由於發布的代碼將無法編譯,並且可能太大而無法推斷出根本原因,因此,我將抓住機會並提示可能出了什么問題。
您的代碼包含兩個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();
...
}
不會引起問題。
好吧,這是因為您現在正在序列化該過程,並且根本沒有並發執行。 我唯一可以得出的結論是,您正在線程之間共享狀態,可能是在TestStub
的構造函數的TestStub
或TestStub.Experiment
參數中。 除非有要執行的代碼,否則我無法聲明共享的內容,但這絕對是原因。
更新資料
考慮了語句stub.Experiment(request);
,我還建議驗證(生成的)Web服務代理和Web服務客戶端框架是否也是線程安全的。 它們可能是發布對象引用,這些引用可能在線程之間使用,因此需要使用適當的鎖進行顯式同步。 可悲的是,沒有簡單的方法來確定一個庫和一組生成的類是否是線程安全的。
您的所有請求都使用相同的模型和屬性。 如果他們有某種狀態-您將得到這種行為。
request[i].setArgs0(model);
request[i].setArgs1(property);
t[i].join();
這並沒有按照您的想法做! 它“暫停”了主要方法! 並且它允許main方法等待t [i]完成。 之后,main方法將恢復該循環。
與直接使用線程相比,通常最好使用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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.