SQL 데이터베이스 (hsqldb)가 있고 내용을 수정하지 않는 여러 쿼리를 실행하려고한다고 가정 해 보겠습니다. 일부 쿼리에는 시간이 오래 걸리고 여러 스레드에서 쿼리를 실행하고 싶습니다. 내 질문은 : 이것을 구현하는 가장 좋은 방법은 무엇입니까?여러 스레드에서 SQL 쿼리 실행 (HSQLDB)
나는 이것을하기위한 좋은 샘플을 찾지 못했고, 다음과 같은 것을 생각해 냈다.
첫 번째로 매우 간략하게 말하면 다음과 같습니다. 쿼리에 액세스하고 결과를 저장하기 위해 thread-safe 컬렉션을 사용합니다. 쿼리는 여러 작업자 스레드에서 실행됩니다. 결과는 모든 스레드가 완료 될 때까지 새로운 결과를 검사하는 주 스레드에서 처리됩니다.
지금 코드 :
쿼리 및 결과 스레드 안전 컬렉션을 만듭니다
ConcurrentLinkedQueue<String> queries = new ConcurrentLinkedQueue<String>()
ConcurrentLinkedQueue<ResultSet> sqlResults = new ConcurrentLinkedQueue<ResultSet>();
스레드의 수를 생성하고 시작 (편집) 다음 내
ExecutorService executorService = Executors.newFixedThreadPool(4);
for(int i=0; i<4; i++){
executorService.execute(new QueryThread(sqlResults, queries));
}
스레드 클래스 QueryThread 왼쪽에있는 한 연결이 열리고 쿼리가 실행됩니다.
private class QueryThread implements Runnable {
private ConcurrentLinkedQueue<ResultSet> sqlResults;
private ConcurrentLinkedQueue<String> queries;
public QueryThread(ConcurrentLinkedQueue<ResultSet> sqlResults, ConcurrentLinkedQueue<String> queries){
this.sqlResults = sqlResults;
this.queries = queries;
}
@Override
public void run(){
Connection connThr = null;
try{
try {
connThr = DriverManager.getConnection(dbModeSave, "sa", "");
connThr.setAutoCommit(false);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String currentQuery;
do {
currentQuery = queries.poll(); // get and remove element from remaining queries
if (currentQuery != null) { // only continue if element was found
try {
Statement stmnt = connThr.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
try {
ResultSet resultSet = stmnt.executeQuery(currentQuery);
sqlResults.add(resultSet);
} catch (SQLException e) {
// (Do something specific)
} finally {
stmnt.close();
}
} catch (SQLException e) {
// (Do something specific)
}
}
} while (currentQuery != null);
} finally {
if (connThr != null) {
try {
connThr.close();
} catch (SQLException e) {
// Nothing we can do?
}
}
}
}
}
스레드가 모두 완료되어 모든 쿼리가 처리 (편집) 된 경우 원래 스레드에서 확인합니다.
while (!executorService.isTerminated()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
while (!sqlResults.isEmpty()) {
ResultSet result = sqlResults.poll();
//process result and close it in the end
}
}
좋아, 그래서 스레드 생성을 ThreadPoolExecutor로 변경했습니다. 고마워요. 하지만 내가 관심있는 부분은 ConcurrentLinkedQueue와 SQL 연산의 사용이다. – user3541377