2014-12-11 4 views
0

아래에이 데이터베이스 오브젝트를 빌드했습니다.java 잠금 및 조건 오브젝트 사용

메서드 업데이트 및 쿼리를 원합니다 : 1. 다중 스레드 방식 (2 스레드가 동시에 액세스 할 수 있음 - 동기화 된 동기화를 방지 할 수 있음)에서 작업하여 mehtod singutare를 추가 할 수 없음) . 2. 하나의 스레드가 데이터베이스를 열었고 두 번째 스레드 (이후에 시작된 스레드)가 해당 데이터베이스를 사용하려고하면 - 아직 두 번째 스레드가 데이터베이스에 액세스하는 상황을 원하지 않습니다 열다. 다른 말로하면 - 나는 그것이 일반적으로 다중 쓰레드이기를 원하지만 쓰레드가 처음으로 데이터베이스를 열 때 쓰레드 안전 (원자 적)을 원한다.

고마워, 아래의 클래스는 내 로직을 삽입해야하는 곳입니다 (보다 구체적으로는 쿼리 및 업데이트 메소드에 해당).

public class SingeltonDB { 
    private static DBconnImpl db = null; 
    private static SingeltonDB singalDb = null; 

    private SingeltonDB(String username, String password) { 
     db = new DBconnImpl(); 
    } 

    public static boolean isOpen() { 
     return (db != null); 
    } 

    public synchronized static SingeltonDB getInstance(String username, 
      String password) throws Exception { 
     if (db != null) { 
      throw (new Exception("The database is open")); 
     } else { 
      System.out.println("The database is now open"); 
      singalDb = new SingeltonDB(username, password); 
     } 
     db.connect(username, password); 
     System.out.println("The database was connected"); 
     return singalDb; 
    } 

    public synchronized static SingeltonDB getInstance() throws Exception { 
     if (db == null) { 
      throw (new Exception("The database is not open")); 
     } 

     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); 
    } 

} 

답변

1

나는 connect 호출을 getInstance 정적 메소드에서 SingeltonDB 생성자로 옮길 것이다. 이것은 정적 db 필드에 대한 참조를 얻을 때마다 db가 열리도록 보장합니다. 또한 모든 비 정적 메서드에 db == null 검사를 추가합니다. 여기

public class SingeltonDB { 
    private static DBconnImpl db = null; 
    private static SingeltonDB singalDb = null; 

    private SingeltonDB(String username, String password) { 
     db = new DBconnImpl(); 
     db.connect(username, password); 
     System.out.println("The database was connected"); 
    } 

    public static boolean isOpen() { 
     return (db != null); 
    } 

    public synchronized static SingeltonDB getInstance(String username, 
      String password) throws Exception { 
     if (db != null) { 
      throw (new Exception("The database is open")); 
     } else { 
      System.out.println("The database is now open"); 
      singalDb = new SingeltonDB(username, password); 
     } 
     return singalDb; 
    } 

    public synchronized static SingeltonDB getInstance() throws Exception { 
     if (db == null) { 
      throw (new Exception("The database is not open")); 
     } 

     return singalDb; 
    } 

    private static void checkDbOpened() throws Exception { 
     if (db == null) { 
      throw new Exception("The database is not open"); 
     } 
    } 

    public void create(String tableName) throws Exception { 
     checkDbOpened(); 
     db.create(tableName); 
    } 

    public User query(String tableName, int rowID) throws Exception { 
     checkDbOpened(); 
     return (db.query(tableName, rowID)); 
    } 

    public void update(String tableName, User user) throws Exception { 
     checkDbOpened(); 
     db.update(tableName, user); 
    } 

} 

테이블이 주어진 TABLENAME 이미 생성하거나하지 않은 경우 결정합니다
public class SingeltonDB { 
    private static DBconnImpl db = null; 
    private static SingeltonDB singalDb = null; 
    private static ConcurrentSkipListSet<String> tableNames = new ConcurrentSkipListSet<String>(); 

    private SingeltonDB(String username, String password) { 
     db = new DBconnImpl(); 
     db.connect(username, password); 
     System.out.println("The database was connected"); 
    } 

    public static boolean isOpen() { 
     return (db != null); 
    } 

    public synchronized static SingeltonDB getInstance(String username, 
      String password) throws Exception { 
     if (db != null) { 
      throw (new Exception("The database is open")); 
     } else { 
      System.out.println("The database is now open"); 
      singalDb = new SingeltonDB(username, password); 
     } 
     return singalDb; 
    } 

    public synchronized static SingeltonDB getInstance() throws Exception { 
     if (db == null) { 
      throw (new Exception("The database is not open")); 
     } 

     return singalDb; 
    } 

    private static void checkDbOpened() throws Exception { 
     if (db == null) { 
      throw new Exception("The database is not open"); 
     } 
    } 

    private static void checkForTable(String tableName) { 
     if (tableNames.add(tableName)) { 
      db.create(tableName); 
     } 
    } 

    public void create(String tableName) throws Exception { 
     checkDbOpened(); 
     checkForTable(tableName); 
    } 

    public User query(String tableName, int rowID) throws Exception { 
     checkDbOpened(); 
     checkForTable(tableName); 
     return (db.query(tableName, rowID)); 
    } 

    public void update(String tableName, User user) throws Exception { 
     checkDbOpened(); 
     checkForTable(tableName); 
     db.update(tableName, user); 
    } 

} 

checkForTable 기능

를 만든 경우를 판별 할 수 있도록 업데이트 된 싱글이다. 그렇지 않은 경우 테이블을 만듭니다. 이 업데이트는 테이블을 사용하기 전에 만들어 졌는지 확인합니다. 이 코드의 문제는 프로세스간에 작동하지 않지만 프로세스 경계를 ​​넘어서 생성되는 테이블을 관리하는 방법을 db 클래스가 알지 못하면 단일 프로세스 내에서만 작동한다는 것입니다.

+0

어떻게 스레드가 안전합니까? 스레드 1이 getInstance를 처음으로 호출하고 스레드 2가 테이블을 작성한 후 - 스레드 1이 아직 끝나지 않았으므로 db가 null로 간주되기 때문에이 바람직한 워크 플로에서 어떤 일이 발생하지 않아야하는지 설명합니다. 은 getInstance가 이러한 시나리오가 발생하지 않도록하는 동기화 된 메서드라는 사실입니다. beacuse synchronized는 * this * 특정 메서드가 한 번에 하나의 스레드에 의해 실행될 수 있다고 알려주지 만 제 경우에는 create()가 동기화되지 않는 것이 문제입니다. – Matoy

+0

이 옵션은 데이터베이스에 액세스하기 전에 데이터베이스가 열리는 것을 보증합니다. 이 솔루션의 문제점은 생성 된 ** tableName **이 각각의 비 생성 호출마다 다를 수 있다는 것입니다. T1은 "foo"테이블을 생성하고 T2는 테이블 "bar"를 생성합니다. T3가 "foo"테이블을 업데이트하려면 테이블 "foo"가 처리되기 전에 만들어 졌는지 확인해야합니다. 클래스는 호출자가 작업을 수행하기 전에 생성 된 테이블에 대한 참조를 포함해야합니다. 나는 그 작업을 수행하기 위해 코드를 업데이트 할 것이다. –