同步泛型方法如何表现?

时间:2014-07-03 12:04:10

标签: java

我对以下类型代码的行为有疑问

  

public synchronized< T>列表与LT; T> executeSelect(Class< T> c){}

如果我执行代码queryEngine.executeSelect(A.class);在一个线程和queryEngine.executeSelect(B.class);在另一个线程中,那些线程将该方法视为一个(并且一个等待另一个)或两个不同的并且它们是同时执行的?

我想拥有一个位于Web服务后面的数据库查询引擎,并从数据库返回给定类型的对象。我还想只使用一个数据库连接并打开/关闭它以便执行查询。

3 个答案:

答案 0 :(得分:2)

synchronized修饰符导致在获取方法返回后释放的隐式监视器后执行的方法。该监视器是:

  • 实例对非static方法执行方法
  • 该方法是针对static方法
  • 定义的

因此,您可以翻译非静态方法

public synchronized <T> List<T> executeSelect(Class<T> c) { 
  // code
}

public <T> List<T> executeSelect(Class<T> c) { 
  synchronized(this) {
    // code
  }
}

事实上,JRockit VM甚至在内部应用了这种翻译,我怀疑HotSpot VM也是如此。

因此,如果方法是使用特定的泛型参数运行并不重要(特别是因为运行时不知道编译后擦除的泛型类型),或者甚至在实例上执行哪个非静态方法方法获取完全相同的监视器。只有调用方法的实例才能确定synchronized修饰符隐式引用哪个监视器。

答案 1 :(得分:0)

通用方法不会导致多个实现。由于类型擦除,它等同于单个synchronized List executeSelect(Class)方法,并且无论特定参数类型如何,两个线程都使用此方法。

通常在同一实例上调用synchronized方法的规则适用 - 多个线程将无法同时执行它。

您可以在thisthis问题中详细了解类型删除,并按照其中提供的链接进行操作。

答案 2 :(得分:0)

泛型仅用于编译时,因此运行时它的行为就像另一个syncronized方法。

public synchronized < T > List< T > executeSelect(Class< T > c) { } 

将编译为

public synchronized List executeSelect(Class c) { } 

如果您调用下面的方法,编译器将知道您将错误的类型作为参数传递,那只是编译时间。

List<String> = obj.<String>executeSelect(new Integer(1));