2013-03-04 25 views
0

我正在一個項目中使用不同模式的不同數據庫中有兩個表。這意味着我有兩個不同的連接參數供這兩個表使用JDBC連接 -每個線程訪問多線程代碼中的數組列表

讓我們假設下面是config.property文件。

TABLES: table1 table2 

#For Table1 
table1.url: jdbc:mysql://localhost:3306/garden 
table1.user: gardener 
table1.password: shavel 
table1.driver: jdbc-driver 
table1.percentage: 80 
table1.columns: COL1,COL2,COl3,Col4,COL5 

#For Table2 
table2.url: jdbc:mysql://otherhost:3306/forest 
table2.user: forester 
table2.password: axe 
table2.driver: jdbc-driver 
table2.percentage: 20 
table1.columns: COL10,COL11,COl12,Col13,COL14 

下面方法將讀取上述config.properties文件,並作出TableConnectionInfo對象爲每個表。

private static void readPropertyFile() throws IOException { 

    prop.load(LnPRead.class.getClassLoader().getResourceAsStream("config.properties")); 

    tableNames = Arrays.asList(prop.getProperty("TABLES").trim().split(",")); 

    for (String arg : tableNames) { 

     TableConnectionInfo ci = new TableConnectionInfo(); 
     ArrayList<String> columns = new ArrayList<String>(); 

     String table = prop.getProperty(arg + ".table").trim(); 
     columns = new ArrayList<String>(Arrays.asList(prop.getProperty(arg + ".columns").split(","))); 

     ci.setTableName(table); 
     ci.setColumns(columns); 

     tableList.put(arg, ci); 
    } 
} 

下面是TableConnectionInfo class,將持有的所有table connection info特定表。

public class TableConnectionInfo { 

    public String tableName; 
    public ArrayList<String> columns; 


    public String getTableName() { 
     return tableName; 
    } 

    public void setTableName(String tableName) { 
     this.tableName = tableName; 
    } 

    public ArrayList<String> getColumns() { 
     return columns; 
    } 

    public void setColumns(ArrayList<String> columns) { 
     this.columns = columns; 
    } 
} 

現在我對線程的指定數量的創建ExecutorService,並把該tableList對象(即我創建通過閱讀config.property file)至Task class構造函數和之後,這tableList對象不會得到任何的修改線程,只有每個線程將訪問值 -

// create thread pool with given size 
ExecutorService service = Executors.newFixedThreadPool(10); 

long startTime = System.currentTimeMillis(); 
long endTime = startTime + (durationOfRun * 60 * 1000); 

for (int i = 0; i < threads; i++) { 
    service.submit(new Task(endTime, tableList)); 
} 

下面是實現Runnable接口

class Task implements Runnable { 

    private static Random random = new SecureRandom(); 
    private final long endTime; 
    private final LinkedHashMap<String, TableConnectionInfo> tableLists; 

    public Task(long endTime, LinkedHashMap<String, TableConnectionInfo> tableList) { 
     this.endTime = endTime; 
     this.tableLists = tableList; 
    } 

    @Override 
    public void run() { 

     while (System.currentTimeMillis() <= endTime) { 

      ..... 

      double randomNumber = random.nextDouble() * 100.0; 
      TableConnectionInfo table = selectRandomTable(randomNumber); 

      /* Below line is Thread Safe right? 
      * And there won't be any issue with it? As I am doing 
      * table.getColumns which will returns me an ArrayList of columns 
      */ 
      final String columnsList = getTableColumns(table.getColumns()); 

      .... 
     } 
     } 

    private String getTableColumns(final List<String> columns) { 

     ... 

    } 
} 
我的任務類

問題陳述: -

在我上面的run方法,我試圖訪問使用table.getColumns特定表getColumns方法和每個線程會做samething。我不確定這是否是線程安全的。它不會導致像比賽條件或其他問題的任何問題。任何想法都會有很大的幫助。

回答

0

這在技術上是線程安全的,只要底層ArrayList在初始構建後沒有變化。這種情況下的每個線程都會引用ArrayList的同一個實例。

如果將來有計劃讓這些表列變化,那麼會導致問題。在這個列表的可變性的情況下,我會構造一個新的列表和指針交換,或者使用java.util.concurrent。*類來保存列表的列表。