有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在JAVA中使用多线程限制到oracle的连接数的多线程解决方案

我有一个线程,它在其中创建到oracle DB的连接,读取内容并写入csv文件。在每个线程中,DB中的内容被写入单独的csv文件。由于建立了n个到DB的连接,它会抛出一个异常,称为“ORA-00018:超出最大会话数”。请提供一个解决方案来停止它,但代码应该同时运行。下面是使用的代码

  host s1 = new host(SYSNAME,SYSID);
  s1.start();

  class host extends Thread{
     String SYSNAME,SYSID;
     public host(String SYSNAME, String SYSID){
        this.SYSNAME = SYSNAME;
        this.SYSID = SYSID;
     }
     public void run(){
        Connection conn;
    try{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        conn = DriverManager.getConnection(url, username, pwd);
        String csv_file = "AverageValuesHost-" + SYSNAME + "-" + SYSID +  "_Result.csv";
        String host_query = null;
        host_query = "My query";
        ResultSet res_host = conn.createStatement().executeQuery(host_query);

        CSVWriter wr = new CSVWriter(new FileWriter(csv_file), ',');
        wr.writeAll(res_host, true);
        wr.flush();
        wr.close();
        conn.close();
    }

共 (2) 个答案

  1. # 1 楼答案

    您需要使用带有连接池的DataSource来创建连接(例如C3P0或HikariCP)。这允许您指定最大连接数,当连接不可用时,线程将被迫等待(直到超时),直到连接可用

    还要注意,创建更多线程并不总是完成更多工作的最佳方式。您还可以考虑使用具有固定数量的线程的^{},并将作业提交给该执行器服务。这样,一次运行的作业不会超过n,因此可以通过这种方式限制连接的数量

    只需确保始终关闭连接(当出现异常时,当前代码无法正确执行此操作)。看看try-with-resources

  2. # 2 楼答案

    你能试试这样的吗。 1.创建自定义线程并在该自定义线程中初始化db连接 2.为fixedThreadPool()创建一个ThreadPoolExecutor,将连接数作为参数传递,并且此TPE应采用自定义线程工厂 3.创建一个可运行类,并访问 3.对于每个查询,创建一个runnable并提交给bq。 4.请勿在Runnable中使用任何等待/通知/或任何其他同步。一旦Runnable开始在线程内执行,它将完成Runnable的执行。它锁定了底层线程。[来自TPE代码]

    这是一种非正统的方法,我从未见过Runnable从Thread(custom)类中取出一个对象来执行。但我没有发现任何问题,如果我错了,有人可以纠正我

    我做了一个原型,请看一看,让我知道它是否符合你的目的。 好吧,这可以在很多方面得到改进,比如异常处理、拒绝处理等。但是首先,应该实现愉快的路径或目的

    谢谢

    package com.stackoverflow.dbconpool;
    
    import java.sql.Connection;
    
    public class DBConnectionThread extends Thread {
        Connection con;
    
        public Connection getCon() {
            return con;
        }
    
        public DBConnectionThread(Runnable r) {
            super(r);
            con = null;// initialize with parameters to make a connection with db.
            // if you want any custom parameter to be passed, you can create a
            // separate Runnable
            // and take values from that runnable to initialize DBConnectionThread.
        }
    
    }
    
    
    package com.stackoverflow.dbconpool;
    
    import java.util.concurrent.ThreadFactory;
    
    public class DBConnectionThreadFactory implements ThreadFactory {
    
        @Override
        public Thread newThread(Runnable r) {
            DBConnectionThread t = new DBConnectionThread(r);
            return t;
        }
    }
    
    
    
    package com.stackoverflow.dbconpool;
    
    import java.sql.Connection;
    import java.util.Random;
    
    public class ExecuteQueryRunnable implements Runnable {
    
        Random rand;
        int index;
    
        public ExecuteQueryRunnable(Random rand, int i) {
            this.rand = rand;
            this.index = i;
        }
    
        @Override
        public void run() {
            System.out.println("Executing DB Query " + index + " inside $$"
                    + Thread.currentThread().getId());
            long threadId = Thread.currentThread().getId();
            DBConnectionThread thread = (DBConnectionThread) Thread.currentThread();
            Connection con = thread.getCon();
            // // execute query code, stament creation etc etc.
            System.out.println("completed executing DB query -" + index
                    + "- inside $$" + Thread.currentThread().getId());
            long threadIdFinish = Thread.currentThread().getId();
            if (threadIdFinish != threadId)
                System.out.println("@@@@@@@@@@@@@@");
        }
    }
    
    
    package com.stackoverflow.dbconpool;
    
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class TestMultiDB {
        public static void main(String[] args) {
            Random rand = new Random();
            ExecutorService es = Executors.newFixedThreadPool(3,
                    new DBConnectionThreadFactory());
            // BlockingQueue<ExecuteQueryRunnable> queryQueue = new
            // ArrayBlockingQueue<ExecuteQueryRunnable>(
            // 10);
            for (int i = 0; i < 10; i++) {
                Runnable r = new ExecuteQueryRunnable(rand, i);
                es.execute(r);
            }
            es.shutdown();
    
            while (!es.isTerminated()) {
            }
            System.out.println("main terminates ");
        }
    }