2013-04-28 40 views
1

我知道互联网上已经有很多类似的问题,但我的问题是关于我的代码,而不是关于线程。我正在制作一个拥有玩家数据库的小应用程序。数据存储类的代码如下。从java中的两个线程同时访问变量

public class DataManager 
{ 
static final int NO_OF_COLUMNS = 18; 
static QDatabase pdb; 

public DataManager() 
{ 
    pdb = new QDatabase(NO_OF_COLUMNS); 
} 

public void addPlayer(Object[] playerData) 
{ 
    pdb.add(playerData); 
} 

public void editPlayerInfo(int type, int playerRegNo, Object data) 
{ 
    pdb.set(type, playerRegNo, data); 
} 

public int getPlayerRegNo(String userID) 
{ 
    return (int) pdb.getData(USER_ID, userID, REG_NO); 
} 

public Boolean contains(int column, Object data) 
{ 
    return pdb.contains(column, data); 
} 
} 

我有不断recieving来自多个客户端的请求,并创造了他们每个人的一个新线程的服务器。他们都访问这个基本上充当数据库的DataManager类。在某种程度上,我是否有可能让所有线程同时调用方法addPlayer()editPlayerInfo(),但由于同步问题而不能混淆整个事件?

我也知道我可以使用数据库。但在这里,我只是认为这会更容易。假设将有大约200个线程同时运行。我解决这个问题的最好方法是什么?

有没有什么办法让我所有的线程在同一时间访问它,否则有200个线程相互等待可能会变得非常慢?

编辑1: 的QDatabase类如下:

public class QDatabase implements Serializable 
{ 
    private ArrayList<ArrayList<Object>> database; 
    public final int NOT_EXISTS = 0, REGULAR = 0, TRANSPOSE = 1; 
    private int lastid = -1; 

    //Initializer taking the number of columns as an argument 
    public QDatabase(int noofcolumns) 
    { 
     database = new ArrayList<ArrayList<Object>>(); 
     addColumns(noofcolumns); 
    } 

    //Method that adds an array of objects as a new row in the database. 
    public void add(Object[] object) 
    { 
     for(int index = 0; index < database.size(); index++) 
     { 
      if(object != null) 
      { 
       database.get(index).add(object[index]); 
       lastid = database.get(0).indexOf(object[0]); 
      } 
     } 
    } 

    //Method that finds the row in a column where an instance of a particular object is found and get the values at a 
    //cell with the same row and a given column. 
    public Object getData(int columntocheck, Object check, int columntoget) 
    { 
     Object ramobject = null; 

     int loc = database.get(columntocheck).indexOf(check); 
     ramobject = database.get(columntoget).get(loc); 

     return ramobject; 
    } 

    //Method to check if a column contains an instance of a given object. 
    public Boolean contains(int column, Object objecttocheck) 
    { 
     return database.get(column).contains(objecttocheck); 
    } 

    //Method to set a given cell to an object. 
    public void set(int column, int row, Object object) 
    { 
     database.get(column).set(row, object); 
    } 
} 

回答

1

QDatabase不是线程安全的。您需要同步所有方法或使用java.util.concurrent包中的ArrayList - CopyOnWriteArrayList的线程安全变体。但是要小心,只有当数据库的读取次数远远超过写入次数时,使用CopyOnWriteArrayList才有意义。请参阅API,它会为所有可变操作创建一个新的无用数组副本。

UPDATE:

其实,在您的情况最有效的solutiion似乎是ReadWriteLock中。使用ReadLock进行所有读取操作,使用WriteLock进行所有可变操作,像这样

public class QDatabase implements Serializable { 
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 
    private Lock readLock = readWriteLock.readLock(); 
    private Lock writeLock = readWriteLock.writeLock(); 
... 
    public void add(Object[] object) { 
     writeLock.lock(); 
     try { 
      ... 
     } 
     } finally { 
      writeLock.unlock(); 
     } 
    } 

    public Object getData(int columntocheck, Object check, int columntoget) { 
     readLock.lock(); 
     try { 
      ... 
     } finally { 
      readLock.unlock(); 
     } 
    } 
... 
+0

我需要多个线程来访问相同的数据库。它是一台服务器。那么,我需要做什么? – Hele 2013-04-28 04:05:34

+0

保持原样。这个类可以并发使用。 – 2013-04-28 04:08:50

+0

你能解释一下这个类对于并发使用是否可行?如果两个或多个线程同时调用editPlayerInfo会发生什么情况? – Hele 2013-04-28 04:13:30

0

只需添加synchronized块

public synchronized void addPlayer(Object[] playerData) 
{ 
    pdb.add(playerData); 
} 

public synchronized void editPlayerInfo(int type, int playerRegNo, Object data) 
{ 
    pdb.set(type, playerRegNo, data); 
} 

这将确保没有两个线程同时访问这个方法。

+0

那很好,但有可能对我来说,让这样所有的线程可以在同一时间访问数据库? – Hele 2013-04-28 03:36:51

+0

@hele在这种情况下,请稍微改述一下您的要求。你想让你的addPlayer和editPlayerInfo成为线程安全,还是你希望它们同时访问这些方法?所有线程将能够同时访问其他方法,而不是根据当前代码来访问这两个方法。 – gurvinder372 2013-04-28 03:43:32

+0

我希望所有线程能够同时访问这些方法,并且不会因此造成任何问题。 – Hele 2013-04-28 03:45:37

0

多线程同时访问但仍保持线程安全的方法之一是使用局部变量或使用ThreadLocal。 你的情况都不可行,所以你不能实现线程的同时访问,它必须是顺序的。

0

查看java.util.concurrency包。你可以使用那里的类来更好地管理你的线程需求。

为了使类/方法“线程安全”,必须这样设计。现在,它并不清楚你的DATABASE对象在内部正在做什么,但它看起来像来自方法名称,多线程将成为一个问题。

为了增加线程数量,但不保持ENTIRE方法同步,查看添加/编辑方法实现的细节,是的,你必须限制线程访问这些代码行,这将导致的问题。

你可以使用像多读原理,单写锁等

+0

关于多次读取和单次写入,只是写入同步的方法和读取方法不是,还是稍微复杂一点? – Hele 2013-04-28 04:07:22