我对以下类型代码的行为有疑问
public synchronized< T>列表与LT; T> executeSelect(Class< T> c){}
如果我执行代码queryEngine.executeSelect(A.class);在一个线程和queryEngine.executeSelect(B.class);在另一个线程中,那些线程将该方法视为一个(并且一个等待另一个)或两个不同的并且它们是同时执行的?
我想拥有一个位于Web服务后面的数据库查询引擎,并从数据库返回给定类型的对象。我还想只使用一个数据库连接并打开/关闭它以便执行查询。
答案 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
方法的规则适用 - 多个线程将无法同时执行它。
答案 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));