繁体   English   中英

使用Thread.join()方法

[英]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的构造函数的TestStubTestStub.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM