2013-02-26 40 views
0

我正在一个项目中使用不同模式的不同数据库中有两个表。因此,这意味着我有这两个表的两种不同的连接参数使用JDBC-插入时使用ConcurrentHashMap时线程安全问题

连接

让我们假设以下是config.property文件 -

TABLES: table1 table2 

#For Table1 
table1.url: jdbc:mysql://localhost:3306/garden 
table1.user: gardener 
table1.password: shavel 
table1.driver: jdbc-driver 

#For Table2 
table2.url: jdbc:mysql://otherhost:3306/forest 
table2.user: forester 
table2.password: axe 
table2.driver: jdbc-driver 

下面的方法将读取上述config.properties文件,并作出每个表的对象为ReadTableConnectionInfo

private static void readPropertyFile() throws IOException { 

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

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

    for (String arg : tableNames) { 

     ReadTableConnectionInfo ci = new ReadTableConnectionInfo(); 

     String url = prop.getProperty(arg + ".url"); 
     String user = prop.getProperty(arg + ".user"); 
     String password = prop.getProperty(arg + ".password"); 
     String driver = prop.getProperty(arg + ".driver"); 

     ci.setUrl(url); 
     ci.setUser(user); 
     ci.setPassword(password); 
     ci.setDriver(driver); 

     tableList.put(arg, ci); 

    } 
} 

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

public class ReadTableConnectionInfo { 

    public String url; 
    public String user; 
    public String password; 
    public String driver; 
    public String percentage; 

    public String getUrl() { 
     return url; 
    } 

    public void setUrl(String url) { 
     this.url = url; 
    } 

    public String getUser() { 
     return user; 
    } 

    public void setUser(String user) { 
     this.user = user; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public String getDriver() { 
     return driver; 
    } 

    public void setDriver(String driver) { 
     this.driver = driver; 
    } 
} 

现在我对线程的指定数量的创建ExecutorService,并把该tableList对象(即我创建通过阅读config.property file)至ReadTask class构造 -

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

for (int i = 0; i < 10; i++) { 
    service.submit(new ReadTask(tableList)); 
} 

下面是我ReadTask类,它实现Runnable interface其中每个线程在做任何有意义的事情之前都会为起始中的每个表创建两个连接。

class ReadTask implements Runnable { 

    private Connection[] dbConnection = null; 
    private ConcurrentHashMap<ReadTableConnectionInfo, Connection> tableStatement = new ConcurrentHashMap<ReadTableConnectionInfo, Connection>(); 

    public ReadTask(LinkedHashMap<String, XMPReadTableConnectionInfo> tableList) { 
     this.tableLists = tableList; 
    } 


    @Override 
    public void run() { 

     try { 

      int j = 0; 
      dbConnection = new Connection[tableList.size()]; 

      //loop around the map values and make the connection list 
      for (ReadTableConnectionInfo ci : tableList.values()) { 

       dbConnection[j] = getDBConnection(ci.getUrl(), ci.getUser(), ci.getPassword(), ci.getDriver()); 
       tableStatement.putIfAbsent(ci, dbConnection[j]); 

       j++; 
      } 

      //do other meaningful thing here 
      } 
     } 
    } 

在我上面的try块,我对存储两个不同的数据库连接,使dbConnection array。然后我有一个tableStatement作为ConcurrentHashMap,其中我存储ReadTableConnectionInfo对象与它的dbConnection。例如Table1对象将在tableStatement ConcurrentHashMap中具有Table1连接。

问题陈述: -

我想看看是否有任何潜在的thread safety issues在这里我有我的tableStatement的ConcurrentHashMap或这里的任何其他线程安全问题插入的方式运行的方法?

回答

0

您的任务类不会在线程之间共享(在您当前的示例中),因此在访问对象内部状态时没有并发问题。目前,你的任务的每个实例中它是由遗嘱执行人分配给线程只访问:

service.submit(new ReadTask(tableList)); 

有了上面的代码行,实例化的ReadTask一个实例,并要求执行在一个运行单独的线程。如果您不访问任何其他线程中的对象,那么您没有并发问题。

在你的例子中,实际上,你不需要使用并发哈希映射(因为你没有提供任何方法来修改该集合的外部对象)。

如果您想要修改代码,请考虑使ReadTableConnectionInfo对象不可变。您可以通过以下方式执行此操作:

  • 将每个类实例变量声明为final。
  • 提供了一个接受的实例变量中的每一个
  • 卸下类setter方法
  • readPropertyFile方法使用新构造函数值的构造函数。
+0

感谢您的建议。我稍微修改了我的'ReadTask类',只是为了更清楚。我不会在任何线程中修改'ReadTableConnectionInfo'类,只是我会做'getXxx调用'。你可以解释一下,你在第一行中提到的“线程之间不共享任务类”是什么意思?为什么我不需要'ConcurrentHashMap'?因为我需要将数据放在Map中吗?所以如果我使用HashMap,那么它可能有可能其他线程搞砸了吗? – AKIWEB 2013-02-26 03:14:24

+0

@ Nevzz03 - 你正在向你的执行者提交一个新的'ReadTask'。在***当前***代码中,它们不在线程之间共享。我想如果你在主线程中同时访问它们,那么你需要更加担心同步问题,但是在你显示的代码中没有发生。 – Perception 2013-02-26 03:17:25

+0

嗯。我有一部分,但我没有得到这一个 - '我想如果你在主线程中同时访问它们'。你能举个例子来说明一下,只是为了让自己更清楚。谢谢。 – AKIWEB 2013-02-26 03:20:05

相关问题