在哪里用多个线程关闭连接/文件/日志?

use*_*412 5 java multithreading threadpool threadpoolexecutor

假设一个简单的双线程场景的以下伪代码:

我有两个线程,我想将数据插入到不同的表到数据库.在thread1上,我想插入一些表,同时,我想将其他数据插入到线程2. 我的问题是如何/在何处放置connection.close(),如果我将它放在线程1上并执行而thread2仍在处理,反之亦然,如果thread2已完成并关闭连接,但thread1尚未完成.

注意,数据库只是一个例子,它可以是文件,logger ..等等.

class Thread1{
    DataBaseConnection connection;
    main(){
        threadPool = Executors.newFixedThreadPool(1);
        connection.open();
        if(ThisMightTakeSomeTime)
        threadPool.submit(new MyRunnable(connection));
        InsertDataToDataBase(Table A, Table B));
        connection.Close(); //What if thread2 isn't done yet?
    }
}

public class MyRunnable implements Runnable {
    MyRunnable(connection){}
    @override
    void Run() { ...}
    void TaskThatMayTakeWhile(){
        ...get data ...
        ...Connection.InsertToTables(table X, table Y)
    }
}
Run Code Online (Sandbox Code Playgroud)

Gra*_*ray 5

我的问题是如何/在哪里放置connection.close(),

首先,据我所知,你应该与2个不同的线程共享一个连接.每个线程都应该拥有自己的数据库连接,可能使用数据库连接池,例如Apache的DBCP.

一旦你有多个连接,我就会让每个线程管理并释放自己的连接回到池中.您应确保在finally块中完成此操作以确保如果存在数据库异常,则仍会释放连接.

如果您被迫让多个线程共享同一个连接,那么他们必须使用它synchronized来确保它们具有对它的独占锁定:

 synchronized (connection) {
    // use the connection
 }
Run Code Online (Sandbox Code Playgroud)

至于何时关闭它,如果它是共享的,你可以有一个共享的使用计数器(可能是AtomicInteger),当计数器变为0时关闭它.或者正如其他人建议你可以使用线程池然后线程池是完成连接.

注意,数据库只是一个例子,它可以是文件,logger ..等等.

就更通用的答案而言,我总是试图反映创建事物的位置.如果一个方法打开流,那么它应该finally关闭流.

 public void someMethod() {
    InputStream stream = ...
    try {
         // process the stream here probably by calling other methods
    } finally {
         // stream should be closed in the same method for parity
         stream.close();
    }
 }
Run Code Online (Sandbox Code Playgroud)

此模式的例外是线程处理程序.那么Thread应该关闭在该流或释放连接finally在的端块run()call()方法.

 public void serverLoopMethod() {
     while (weAcceptConnections) {
        Connection connection = accept(...);
        threadPool.submit(new ConnectionHandler(connection);
     }
 }
 ...
 private static class ConnectionHandler implements Runnable {
     private Connection connection;
     public ConnectionHandler(Connection connection) {
         this.connection = connection;
     }
     // run (or call) method executed in another thread
     public void run() {
         try {
            // work with the connection probably by calling other methods
         } finally {
              // connection is closed at the end of the thread run method
              connection.close();
         }
     }
 }
Run Code Online (Sandbox Code Playgroud)