如何防止在异步线程中修改对象?

时间:2014-12-19 12:52:47

标签: java multithreading spring

我有一个web服务响应对象,我想直接处理它,并使用它来执行一个长时间运行的例程,使用Spring @Async

问题:在直接过程中,我必须修改对象,因为它是mutable,修改也会反映在异步过程中。

我该如何防止这种情况?

示例:

List<String> list = Arrays.asList("one", "two");
asyncService.process(list); //should process all items in the list, even though the next statement will remove some
list.remove(0);

@Service
public class AsyncService {
  @Async
  public void process(List<String> list) {
     //process the list
  }
} 

我知道 - 对于一个简单的列表 - 我基本上可以克隆列表并将其交给异步进程。

但是对于一个带有几个嵌套列表的复杂xml对象(比如10个节点左右 - 我无法控制它),这可能是一个很大的混乱,因为我必须保留xml对象的完整内容。 / p>

1 个答案:

答案 0 :(得分:0)

您需要使用回调模式。非常基本的示例(使用Java 8表示法,但您可以将其替换为Runnable

asyncService.process(list, ()-> list.remove(0));

并在process

public void process(List<> list, Runnable callback){
   // your logic here
   Arrays.stream(callbacks).foreach(Runnable::run)
}

但这是解决方案。不是很有弹性......

对于更具弹性的解决方案,您可以像这样创建AsyncService

class AsyncService {

    @Async
    public void process(Runnable codeTooCall, Runnable... callbacks){
        codeTooCall.run();
        Arrays.stream(callbacks).forEach(Runnable::run);
    }
}

现在您可以进行任何调用异步,只需注入asyncService然后:

asyncService.process(()-> notAsyncService.process(list),  ()-> list.remove(0))

但你应该注意“双向异步”并从原始方法中删除@Async