@ user207421 был прав, что метод getDataSource () должен быть синхронизирован, и, конечно, я уже пробовал это; однако это все еще не решило мою проблему потока «0», не позволяющего другим потокам выполнять ход.
Я удалил все из моего кода, всех других библиотек и c .., пока не заставил его работать, а затем снова начал создавать его резервную копию, чтобы найти точку разрыва. Похоже, что главным определяющим фактором является размер ResultSet. Я попытался добавить дополнительное время thread.sleep в разных местах, однако единственное, что сработало, - это разбить запросы на меньшие ResultSets.
600 тыс. Наборов результатов, будет запущен только 1 поток, 1 тыс. Наборов результатов и 4 потока. Если ResultSets содержит только 100 строк, все 11 потоков будут выполняться. Обратите внимание: я тестировал это на системе с 16 процессорами с 8 ГБ памяти, выделенной для JVM (aws m5.4xlarge), поэтому аппаратные ресурсы не должны были быть фактором. Думаю, мне просто нужно разбить код на более мелкие куски.
Когда я изначально изучал это, я был удивлен отсутствием конкретных примеров кода c для этой конкретной c проблемы (независимо от размера ResultSet и количества потоков), поэтому я просто разместил здесь то, что наконец сработало для меня, ради полного примера кода:
import java.sql.*;
import org.apache.commons.dbcp2.BasicDataSource;
public class SandboxApp {
private static BasicDataSource dataSource;
public static synchronized BasicDataSource getDataSource() {
if (dataSource == null) {
BasicDataSource ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/my-db");
ds.setUsername("root");
ds.setPassword("");
ds.setDriverClassName("org.mariadb.jdbc.Driver");
ds.setInitialSize(3);
ds.setMaxTotal(25);
ds.setMinIdle(0);
ds.setMaxIdle(8);
ds.setMaxOpenPreparedStatements(100);
dataSource = ds;
}
return dataSource;
}
public static void main(String [] args) throws Exception{
for(int i=0; i<11; i++){//spawn 11 threads & get each thread to process 100 sql rows at the same time
new Thread("" + (i*100)){
public void run(){
System.out.println("Thread: " + getName() + " running");
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = SandboxApp.getDataSource().getConnection();
pstmt = con.prepareStatement("select something from some_table limit "+getName()+",100");
rs=pstmt.executeQuery();
while(rs.next()){
System.out.println("Doing stuff for thread "+getName());//With smaller ResultSet, this works fine for all 11 threads
//give the other threads a turn...
try {
Thread.sleep(10);
}
catch(InterruptedException ex) {
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {pstmt.close();} catch (SQLException e) {}
try { con.close(); } catch(Exception e) {}
try { rs.close(); } catch(Exception e) {}
}
}
}.start();
}
}
}