繁体   English   中英

Java同步,线程安全性,包装对象和竞争条件

[英]Java synchronization, thread safety, wrapped objects, and race conditions

我正在一个带有线程池的系统上工作,该线程池将提交链接的任务。 每个任务将运行,检查其结果,然后根据结果执行另一个任务。 这是在同一线程中完成的,因此它不会将作业重新提交回线程池。 每个任务都会将其结果添加到包装Collection的对象中,并提供其他一些次要功能,然后将其传递给链中的下一个任务。 到达链的末端后,结果将在Future.get()中返回并带有超时,然后可以分析整个结果。

每个任务将调用一个外部服务,即SOAP请求。 如果任务挂起,则可能正在等待并等待响应。 在这种情况下,如果get()超时,我将捕获TimeoutException并取消对(true)的将来。 这意味着将InterruptedException抛出在任务线程中(因为它很可能处于等待状态)并可以被捕获。 异常包装在响应对象中,并放置在Collection包装器中。

现在,如果超时,似乎无法从Future对象取回该集合。 我正在查看原始任务(或任务的包装器),如果捕获了TimeoutException且取消了Future,则从原始任务中检索Collection包装器,该包装器应包含直到暂停。

但是,我不知道这本身是线程安全还是争用条件。 如果主线程在取消Future对象后立即尝试访问包装的Collection,包装的异常是否在那里? 在并发迭代和修改的尝试中会结束吗? 有没有一种方法可以确保在主线程检索到包装的异常之前将其包装到该集合中?

一些Q&D示例代码:

public class MyCallable implements Callable<MyResponseCollection> {

    private MyResponseCollection responses = new MyResponseCollection();  //Wraps a List
    private MyTask task; //This is set prior to submitting the task wrapper

    public MyResponseCollection call() throws Exception() {
        task.setCollection(responses);
        task.call(); //kicks off the task chain, not an override to Callable.call
        return responses; //If all goes well, this is passed into the Future
    }
}

public class MyTask {

    private MyResponseCollection responses;

    public void setCollection(MyResponseCollection responses){
        this.responses = responses;
    }

    public void call(){
        try{
            MyResponse m = this.doStuff();
            responses.add(m);
            this.executeNext(m); //Runs the next task based on the response, simplified here, responses object passed into the next task

        } catch (InterruptedException e){
            responses.add(new ExceptionResponse(e)); //Here's where we catch that potential interrupt
        }
     }
     public MyResponse doStuff() throws InterruptedException{
         //All work done here
     }
}

这是我第一次尝试多线程,因此我不确定如何确保线程等之间的操作顺序,或者我是否在这里做一些愚蠢的事情,还有更好的解决方案。 MyResponseCollection上的syncnize()块也适用于其中的List吗? 是否要求所说的List也是一个Collections.synchronizedList?

为了让一个线程在释放资源时指示另一个线程,我将向该资源添加一个Semaphore isDone字段。

public class MyResponseCollection {
    public final Semaphore isDone = new Semaphore(0);
}

public class MyCallable implements Callable<MyResponseCollection> {
    ...
    public MyResponseCollection call() throws Exception() {
        task.setCollection(responses);
        task.call(); //kicks off the task chain, not an override to Callable.call
        responses.isDone.acquire();
        return responses; //If all goes well, this is passed into the Future
    }
}


public class MyTask {
    ...

    public void call(){
        try{

        } finally {
            responses.isDone.release();
        }
     }
 }

responses.isDone.acquire()将阻塞,直到获得可用许可为止,并且将isDone初始化为零许可。 MyTask#call()在其finally块中添加一个许可,这会唤醒MyCallable

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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