2012-03-24 3 views
0

.csv 파일에서 항목을 읽고 원격 데이터베이스에 기록하는 프로그램을 다루고 있습니다. 나는 프로그램을 멀티 쓰레딩하려고 노력하고있다. 그리고 그 목적을 위해 나는 별개의 연결을 가진 2 개의 프로세스 쓰레드를 만들었다. 이를 위해 .csv 파일을 버퍼링 된 판독기로 읽어 들이고 버퍼링 된 판독기의 내용을 처리합니다. 그러나 스레드가 데이터를 복제하는 것으로 보입니다 (모든 튜플의 복사본 두 개를 데이터베이스에 쓰는 것).버퍼링 된 리더와 우선 순위 큐가 함께 작동합니까?

저는 Java에서 버퍼를 뮤텍스하는 방법을 알아 내려고 노력해 왔습니다. 가장 가까운 것은 우선 순위 큐입니다.

제 질문은 버퍼링 된 리더를 사용하여 파일을 줄 단위로 우선 순위 대기열로 읽을 수 있습니까? I.E.

public void readFile(Connection connection) { 
     BufferedReader bufReader = null; 
     try{ 
      bufReader = new BufferedReader(new FileReader(RECS_FILE)); 
      bufReader.readLine(); //skip header line 
      String line; 
      while((line = bufReader.readLine()) != null) { 
       //extract fields from each line of the RECS_FILE 
       Pattern pattern = Pattern.compile("\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\",\"([^\"]+)\""); 
       Matcher matcher = pattern.matcher(line); 
       if(!matcher.matches()) { 
        System.err.println("Unexpected line in "+RECS_FILE+": \""+line+"\""); 
        continue; 
       } 
       String stockSymbol = matcher.group(1); 
       String recDateStr = matcher.group(2); 
       String direction = matcher.group(3); 
       String completeUrl = matcher.group(4); 

       //create recommendation object to populate required fields 
       // and insert it into the database 
       System.out.println("Inserting to DB!"); 
       Recommendation rec = new Recommendation(stockSymbol, recDate, direction, completeUrl); 
       rec.insertToDb(connection); 
      } 
     } catch (IOException e) { 
      System.err.println("Unable to read "+RECS_FILE); 
      e.printStackTrace(); 
     } finally { 
      if(bufReader != null) { 
       try{ 
        bufReader.close(); 
       } catch (IOException e) { 
       } 
      } 
     } 

    } 

.csv 파일을 읽는 데 버퍼링 된 리더가 사용됩니다. 함수 외부에서 우선 순위 큐를 설정하여 버퍼링 된 판독기가 우선 순위 큐에 튜플을 넣고 각 프로그램 스레드가 우선 순위 큐에 액세스하도록하는 방법이 있습니까?

답변

1

버퍼 된 판독기 또는 실제로 모든 판독기 또는 스트림은 본질적으로 단일 스레드 전용입니다. 우선 순위 큐는 실제 구현에 따라 여러 스레드에서 사용할 수도 있고 사용하지 않을 수도있는 완전히 별개의 구조입니다. 그래서 짧은 대답은 : 아니오, 그들은 두 개의 전혀 관련이없는 개념입니다.

원래 문제를 해결하려면 여러 스레드에서 스트림 된 파일 액세스를 사용할 수 없습니다. 이론상으로 RandomAccessFile을 사용할 수 있습니다. 단, 선이 너비가 고정되어 있지 않으므로 해당 점까지 파일의 모든 것을 읽지 않고 행의 시작 부분에 seek()을 입력 할 수 없습니다. 또한 데이터가 고정 된 레코드로 구성되어 있더라도 두 개의 다른 스레드로 파일을 읽는 것은 비현실적입니다.

당신이 병렬화 할 수있는 유일한 방법은 각 스레드에 대해 별도의 트랜잭션을 사용해야하므로 트랜잭션 삽입을 잊어 버린 명백한 경고가있는 데이터베이스 삽입입니다. (그렇지 않으면 데이터베이스 작업을 동기화해야하는데, 이는 다시는 아무것도 얻지 못했음을 의미합니다.)

따라서 한 스레드에서 행을 읽고 문자열을 전달하여 해결할 수 있습니다. ExecutorService을 통해 호출 된 처리 메소드. 그것은 잘 확장되지만 다시 경고가 있습니다. 데이터베이스 잠금의 오버 헤드가 증가하면 다중 스레드를 사용하는 이점이 무력화됩니다.

궁극적 인 교훈은 사물을 지나치게 복잡하게 만드는 것이 아닙니다. 간단한 방법을 시도해보십시오. 간단한 방법 만 시도해도 더 복잡한 해결책을 찾아보십시오. 다른 교훈은 아마도 멀티 스레딩이 I/O 경계 프로그램을 돕지 않는다는 것입니다.

0

@ Biziclop의 답변은 (+1)이지만 나는 대량 데이터베이스 삽입에 대해 뭔가를 추가 할 것이라고 생각했습니다.

모르는 경우에는 대부분의 SQL 데이터베이스에서 데이터베이스 자동 커밋을 해제하는 것이 대량 삽입 중에 큰 이점입니다. 일반적으로 각 SQL 문 다음에 데이터베이스는 인덱스를 갱신하고 디스크 구조에 대한 모든 변경을 수행하는 디스크 저장 영역으로 커미트합니다. 이 자동 커밋을 해제하면 데이터베이스는 commit 마지막에 전화하면 이러한 변경 작업 만 수행하면됩니다. 자동 커밋은 트랜잭션이 같은 일을 수행에 종종 삽입을 포장, 데이터베이스에 의해 지원되지 않는 경우, 또한

conn.setAutoCommit(false); 
for (Recommendation rec : toBeInsertedList) { 
    rec.insertToDb(connection); 
} 
conn.setAutoCommit(true); 

: 일반적으로 당신이 뭔가를 할 것입니다.

을 : 여기

도움이 될 몇 가지 다른 답변입니다