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) {

      ...

     }
}

问题陈述:-

在我上面的运行方法中,我试图访问getColumns特定表的方法,table.getColumns并且每个线程都将做同样的事情。我不确定这是否是线程安全的。它不会给我带来任何问题,比如比赛条件或其他问题。任何想法都会有很大帮助。

4

1 回答 1

0

只要底层 ArrayList 在初始构造后没有更改,这在技术上是线程安全的。在这种情况下,每个线程都将引用同一个 ArrayList 实例。

如果将来有计划使这些表列可变,则会导致问题。在此列表可变的情况下,我将构建一个新列表和指针交换或使用 java.util.concurrent.* 类来保存您的列列表。

于 2013-03-04T00:44:04.187 回答