简体   繁体   English

跨线程共享jdbc“连接”

[英]Sharing a jdbc “Connection” across threads

I have a main thread that runs periodically. 我有一个定期运行的主线程。 It opens a connection, with setAutoCommit(false), and is passed as reference to few child threads to do various database read/write operations. 它使用setAutoCommit(false)打开一个连接,并作为对少数子线程的引用传递,以执行各种数据库读/写操作。 A reasonably good number of operations are performed in the child threads. 在子线程中执行相当多的操作。 After all the child threads had completed their db operations, the main thread commits the transaction with the opened connection. 在所有子线程完成其数据库操作之后,主线程将使用打开的连接提交事务。 Kindly note that I run the threads inside the ExecutorService. 请注意,我在ExecutorService中运行线程。 My question, is it advisable to share a connection across threads? 我的问题是,建议跨线程共享连接吗? If "yes" see if the below code is rightly implementing it. 如果“是”,请查看以下代码是否正确实现它。 If "no", what are other way to perform a transaction in multi-threaded scenario? 如果“否”,在多线程场景中执行事务的其他方法是什么? comments/advise/a-new-idea are welcome. 欢迎提出意见/建议/新意见。 pseudo code... 伪代码......

Connection con = getPrimaryDatabaseConnection();
// let me decide whether to commit or rollback
con.setAutoCommit(false);

ExecutorService executorService = getExecutor();
// connection is sent as param to the class constructor/set-method
// the jobs uses the provided connection to do the db operation
Callable jobs[] = getJobs(con); 
List futures = new ArrayList();
// note: generics are not mentioned just to keep this simple
for(Callable job:jobs) {
    futures.add(executorService.submit(job));
}
executorService.shutdown();
// wait till the jobs complete
while (!executorService.isTerminated()) {
  ;
}

List result = ...;
for (Future future : futures) {
    try {
       results.add(future.get());
    } catch (InterruptedException e) {
      try {
        // a jobs has failed, we will rollback the transaction and throw exception
        connection.rollback();
        result  = null;
        throw SomeException();
      } catch(Exception e) {
       // exception
      } finally {
         try {
           connection.close();
         } catch(Exception e) {//nothing to do}
      }    
   }
}
// all the jobs completed successfully!
try {
  // some other checks
  connection.commit();
  return results;
} finally {
  try {
      connection.close();
  } catch(Exception e){//nothing to do}
}

I wouldn't recommend you to share connection between threads, as operations with connection is quite slow and overall performance of you application may harm. 我不建议您在线程之间共享连接,因为连接操作非常慢并且应用程序的整体性能可能会受到损害。

I would rather suggest you to use Apache Connections Pool and provide separate connection to each thread. 我宁愿建议您使用Apache Connections Pool并为每个线程提供单独的连接。

You could create a proxy class that holds the JDBC connection and gives synchronized access to it. 您可以创建一个代理类来保存JDBC连接并提供对它的同步访问。 The threads should never directly access the connection. 线程永远不应该直接访问连接。

Depending on the use and the operations you provide you could use synchronized methods, or lock on objects if the proxy needs to be locked till he leaves a certain state. 根据您提供的用途和操作,您可以使用synchronized方法,或者如果代理需要锁定直到他离开某个状态,则锁定对象。


For those not familiar with the proxy design pattern. 对于那些不熟悉代理设计模式的人。 Here the wiki article . 这里是维基文章 The basic idea is that the proxy instance hides another object, but offers the same functionality. 基本思想是代理实例隐藏了另一个对象,但提供了相同的功能。

In this case, consider creating a separate connection for each worker. 在这种情况下,请考虑为每个工作人员创建单独的连接。 If any one worker fails, roll back all the connections. 如果任何一个工作程序失败,则回滚所有连接。 If all pass, commit all connections. 如果全部通过,则提交所有连接。

If you're going to have hundreds of workers, then you'll need to provide synchronized access to the Connection objects, or use a connection pool as @mike and @NKukhar suggested. 如果您将拥有数百名工作人员,那么您需要提供对Connection对象的同步访问,或者使用@mike和@NKukhar建议的连接池。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM