在多线程环境中使用静态内部类的任何陷阱?

时间:2010-12-16 11:54:13

标签: java multithreading inner-classes

这是我第一次涉足多线程领域,目前我正在使用Java并发库实现解决方案。代码本质上接受许多服务请求,异步提交所有请求,并在所有服务完成后返回响应映射。我的代码看起来像这样:

public OuterClass {

  public IResponseMap sendAsynchronousRequests(IRequest... dataList) {
    List<RepositoryFutureTask<IRequest>> futures = new ArrayList<RepositoryFutureTask<IRequest>>();

    //create one future for each request in the list
    for (final IRequest request : dataList) {
        RepositoryFutureTask<IRequest> future = new RepositoryFutureTask<IRequest>(request.getId(), new Callable<IRequest>() {
            public IResponse call() {
                return request.getService().callService(request.getRequestData());
            }
        });
        futures.add(future);
    }

   //Submit each future for execution
   for(Future future:futures) {
      //Singleton ReqeustExecutorService maintains a pool of threads via
      // java.util.concurrent.ExecutorService
      RequestExecutorService.execute(future);
   }

   //Block processing until all requests have finished and add responses to map
   //based on id as they finish
   IResponseMap responseMap = new ResponseMap();
   for(RepositoryFutureTask future:futures) {
      responseMap.put(future.getId(), future.get());
   }


    return responseMap;
  }

static class RepositoryFutureTask extends FutureTask<IResponse> {
     private String id;

    public RepositoryFutureTask(String theId, Callable<IResponse> callable) {
        super(callable);
          id = theId;
    }
    //standard getter for id omitted for conciseness
}
}

我主要感兴趣的是我的静态内部类解决方案是否会在多线程环境中产生任何问题,但也会对上述解决方案的任何其他评论感兴趣。请注意,上面的代码有可能不完美,因为它仍然有点伪代码,我已经将它大量化了。错误处理也已被删除。提前谢谢。

3 个答案:

答案 0 :(得分:3)

不,静态内部类的加载方式与顶级类相同。见JLS的8.5.2 - http://java.sun.com/docs/books/jls/third_edition/html/classes.html

答案 1 :(得分:3)

如果在静态嵌套类中有一个synchronized静态方法,它将在外部类中锁定另一个对象。我真的建议在任何方法上使用synchronized修饰符,尤其是静态方法。

匿名内部类的问题更多,this上的锁定会有所不同。即使你写synchronized (this) {,它也不是那么明显。我已经看过几次了。

从理论上讲,如果嵌套类静态初始化程序与外部nester类静态初始化程序并行运行,我猜你可能会遇到麻烦。从技术上讲,这与在两个外部类中运行静态intiailser相同,但您更可能与嵌套类具有循环依赖性。

答案 2 :(得分:1)

使用静态内部类没有问题。唯一的问题是private String id;不是final。设为final,你就可以了解线程安全性; - )