我在作业期间给了一个任务来实现一个玩具Singelton数据库和一个使用Spring依赖注入来利用该数据库的用户控制器。 我推出了这个版本:
Singelton DB
package SingeltonDBVersion2;
import GlobalSetting.User;
public class SingeltonDB {
private static DBconnImpl db = null;
private static SingeltonDB singalDb = null;
private SingeltonDB(String username, String password) {
db = new DBconnImpl();
}
public synchronized static SingeltonDB getInstance(String username,
String password) throws Exception {
if (db != null) {
return singalDb;
}
System.out.println("The database is now open");
singalDb = new SingeltonDB(username, password);
db.connect(username, password);
System.out.println("The database was connected");
singalDb.create("table1");
return singalDb;
}
public void create(String tableName) throws Exception {
db.create(tableName);
}
public User query(String tableName, int rowID) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return null;
}
return (db.query(tableName, rowID));
}
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);
}
}
UserContorller
package SingeltonDBVersion2;
import GlobalSetting.IUserContorller;
import GlobalSetting.User;
/****************************************************************************
* This is class is an implementation of a UserContorller for the version with
* Spring, because here we use inversion of control. The UserContorller
* constructor takes the an object of SingeltonDB which we are passing using
* Spring Dependency Injection in our UnitTests
*****************************************************************************/
public class UserContorller implements IUserContorller {
SingeltonDB db;
public UserContorller(SingeltonDB db) throws Exception {
this.db = db;
}
@Override
public void createTable(String table) throws Exception {
db.create(table);
}
@Override
public void saveUser(String table, int id, String name, int age)
throws Exception {
db.update(table, new User(id, name, age));
}
@Override
public User getUser(String table, int id) throws Exception {
return db.query(table, id);
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="MyUserContorller" class="SingeltonDBVersion2.UserContorller">
<constructor-arg ref="MySingeltonDB" />
</bean>
<bean id="MySingeltonDB" class="SingeltonDBVersion2.SingeltonDB"
factory-method="getInstance">
<constructor-arg value="MyAccount" />
<constructor-arg value="123" />
</bean>
</beans>
我可以这样使用它:
ApplicationContext contex = new ClassPathXmlApplicationContext("spring.xml");
UserContorller user1 = (UserContorller) contex.getBean("MyUserContorller");
saveUser("table1", 1, Mike, 44); //add user with id 1 and age of 44
现在,我被要求编写一个测试(比如一个Junit),如果SingeltonDB的getinstance()方法不同步,将会失败... 我真的不知道该怎么做......
有人可以帮助提供灵魂吗? 谢谢!
答案 0 :(得分:0)
默认情况下,所有单例bean都会在创建上下文时实例化。所以在你的情况下避免使用:
<bean id="MyUserContorller" class="SingeltonDBVersion2.UserContorller" lazy-init="true">
....
<bean id="MySingeltonDB" class="SingeltonDBVersion2.SingeltonDB" factory-method="getInstance" lazy-init="true">
现在创建多个线程,如下所示:
class MyThread extends Thread {
private ApplicationContext context;
private int hashCode;
public MyThread(ApplicationContext context) {
this.context = context;
}
public void run() {
hashCode = System.identityHashCode(context.getBean("MySingeltonDB"));
}
public int getHashCode() {
return hashCode;
}
}
现在创建多个线程实例并将它们全部启动,并在hashcode上断言,形成每个线程的非相等性。如果你得到平等,你的考试就会失败,你想要的是什么。
答案 1 :(得分:-1)
almas shaikh,这是我写的代码:
package Tests;
import java.util.concurrent.CountDownLatch;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SingeltonDBVersion2TestSynch {
static ApplicationContext Context;
@Test
public void testSynch() throws Exception {
int num = 100;
Context = new ClassPathXmlApplicationContext("spring.xml");
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(num);
MyThread[] threads = new MyThread[num];
for (int i = 0; i < threads.length; i++) {
threads[i] = new MyThread(Context, startSignal, doneSignal);
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
startSignal.countDown();
doneSignal.await();
for (int i = 0; i < threads.length; i++) {
System.out.println(threads[i].getHashCode());
}
}
}
class MyThread extends Thread {
private ApplicationContext context;
private int hashCode;
CountDownLatch startSignal;
CountDownLatch doneSignal;
public MyThread(ApplicationContext context, CountDownLatch startSignal,
CountDownLatch doneSignal) {
this.context = context;
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
public void run() {
try {
startSignal.await();
hashCode = System
.identityHashCode(context.getBean("MySingeltonDB"));
doneSignal.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getHashCode() {
return hashCode;
}
}
我只是尝试打印哈希码以进行检查......但它们都具有相同的哈希码(我更改了spring xml并从getInstacnec()中删除了eynchronized)。 myabe我在CountDownLacths中没有使用正确的方法吗?