Java 跨线程共享 jdbc“连接”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18897092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 12:05:18  来源:igfitidea点击:

Sharing a jdbc "Connection" across threads

javamultithreadingjdbctransactions

提问by Vijay Veeraraghavan

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. 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. 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...

我有一个定期运行的主线程。它使用 setAutoCommit(false) 打开一个连接,并作为参考传递给几个子线程以执行各种数据库读/写操作。在子线程中执行了相当多的操作。在所有子线程完成它们的数据库操作后,主线程使用打开的连接提交事务。请注意,我在 ExecutorService 中运行线程。我的问题是,是否建议跨线程共享连接?如果“是”,看看下面的代码是否正确地实现了它。如果“否”,在多线程场景中执行事务的其他方式是什么?欢迎评论/建议/新想法。伪代码...

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}
}

回答by mike

You could create a proxy class that holds the JDBC connection and gives synchronized access to it. The threads should never directly access the connection.

您可以创建一个代理类来保存 JDBC 连接并提供对它的同步访问。线程不应该直接访问连接。

Depending on the use and the operations you provide you could use synchronizedmethods, 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.

对于那些不熟悉代理设计模式的人。这里是维基文章。基本思想是代理实例隐藏另一个对象,但提供相同的功能。

回答by nkukhar

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 Pooland provide separate connection to each thread.

我宁愿建议您使用Apache 连接池并为每个线程提供单独的连接。

回答by Sam Barnum

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.

在这种情况下,请考虑为每个工作人员创建一个单独的连接。如果任何一个 worker 失败,回滚所有连接。如果全部通过,则提交所有连接。

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 建议的连接池。