【发布时间】:2014-12-17 11:15:19
【问题描述】:
我有这个我已经构建的 singelton 数据库,以及我创建的这个 Junit 测试:
单身
package SingeltonDBVersion1;
import GlobalSetting.User;
/****************************************************************************
* This is the SingeltonDB. it warps the object DBconn according to the
* Singleton pattern. it receive name and password (i.e. DBConn parameters) and
* if it is the first time that a UserContorll try to get an instance it connect
* to the database. After that, the DBConn instance will be return to the user.
*****************************************************************************/
public class SingeltonDB {
private static DBconnImpl db = null;
private static SingeltonDB singalDb = null;
boolean first = true;
private SingeltonDB(String username, String password) {
if (first) {
try {
System.out.println("first");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
first = false;
}
db = new DBconnImpl();
}
public static SingeltonDB getInstance(String username, String password)
throws Exception {
if (db != null) {
return singalDb;
}
singalDb = new SingeltonDB(username, password);
System.out.println("The database is now open");
db.connect(username, password);
System.out.println("The database was connected");
return singalDb;
}
public void create(String tableName) throws Exception {
db.create(tableName);
}
public User query(String tableName, int userID) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return null;
}
return (db.query(tableName, userID));
}
public void update(String tableName, User user) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return;
}
db.update(tableName, user);
}
public void disconnect() throws Exception {
db.disconnect();
}
public static void reset() throws Exception {
db = null;
}
}
朱尼特
package Tests;
import java.util.concurrent.CountDownLatch;
import org.junit.Test;
import SingeltonDBVersion1.SingeltonDB;
public class SingeltonDBVersion1Tests {
@Test
public synchronized void testSynch() throws Exception {
int num=2;
CountDownLatch doneSignal = new CountDownLatch(num);
MySingeltonDB[] instances = new MySingeltonDB[num];
for (int i = 0; i < num; i++) {
instances[i]=new MySingeltonDB(doneSignal);
}
SingeltonDB.reset();
for (int i = 0; i < num; i++) {
instances[i].run();
}
doneSignal.await();
for (int i = 0; i < num; i++) {
for (int j = i; j < instances.length; j++) {
if (instances[i].getDB()!=instances[j].getDB())
{
throw (new Exception());
}
}
}
}
class MySingeltonDB implements Runnable {
SingeltonDB db;
CountDownLatch doneSignal;
public MySingeltonDB(CountDownLatch doneSignal) {
this.db = null;
this.doneSignal = doneSignal;
}
public SingeltonDB getDB() {
return db;
}
@Override
public void run() {
try {
this.db = SingeltonDB.getInstance("MyAccount", "123");
doneSignal.countDown();
System.out.println("----------------------------------------->"+db );
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
我在这里要做的是创建 2 个单例实例,当且仅当 singletonDB 方法:getInstance() 不同步。但由于某种原因,即使我没有在方法中使用同步,单例也可以正常工作并返回该类的一个实例。
【问题讨论】:
-
您似乎是按顺序创建实例,因此您的伪单例很可能在这种情况下实际上作为单例工作。
-
我会尝试使用
Executor并创建更多实例 - 2 太有限了。虽然最后,如果您使用真正的单例习语,使用单元测试来检查单例是否是实际的单例将毫无意义(即您可以省去单元测试)。 -
我是按顺序创建实例,但是每个实例的getInstnace调用都是在线程run()方法中完成的,所以不符合并行吗?
-
我知道,但这是我在求职面试中被问到的一个问题,看我是否足够了解线程......
-
是否要求“编写一个如果给定单例类的 getInstance() 方法不同步将失败的 JUnit 测试”?
标签: java multithreading junit synchronization thread-safety