2013-07-30 3 views
0

멀티 스레딩을 사용하여 이번에 만 완료 한 작업을 수행하고 싶습니다. 파일에서 한 줄씩 많은 양의 데이터를 읽고 각 줄의 정보를 얻어 맵에 추가해야합니다. 이 파일은 백만 라인 이상이므로 멀티 스레딩의 이점을 누릴 수 있다고 생각했습니다.멀티 스레딩을 효과적으로 사용하는 방법

Java에서 멀티 쓰레딩을 한 번도 사용해 본 적이 없기 때문에 여기에 대한 방법은 확실하지 않습니다. main 메소드에 읽기를 수행 한 다음 다른 스레드로 읽은 행을 제공하여 String을 형식화 한 다음 다른 스레드에 전달하여 맵에 넣고 싶습니다.

public static void main(String[] args) 
{ 
    //Some information read from file 
    BufferedReader br = null; 
    String line = ''; 
    try { 
     br = new BufferedReader(new FileReader("somefile.txt")); 
     while((line = br.readLine()) != null) { 
      // Pass line to another task 
     } 


    // Here I want to get a total from B, but I'm not sure how to go about doing that 

} 


public class Parser extends Thread 
{ 
    private Mapper m1; 

    // Some reference to B 
    public Parse (Mapper m) { 
     m1 = m; 
    } 

    public parse (String s, int i) { 
     // Do some work on S 
     key = DoSomethingWithString(s); 
     m1.add(key, i); 
    } 

} 

public class Mapper extends Thread 
{ 
    private SortedMap<String, Integer> sm; 
    private String key; 
    private int value; 
    boolean hasNewItem; 

    public Mapper() { 
     sm = new TreeMap<String, Integer>; 
     hasNewItem = false; 
    } 

    public void add(String s, int i) { 
     hasNewItem = true; 
     key = s; 
     value = i; 
    } 

    public void run() { 
     while (!Thread.currentThread().isInterrupted()) { 
      try { 
       if (hasNewItem) { 
        // Find if street name exists in map 
        sm.put(key, value); 
        newEntry = false; 
       } 
      } catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
      } 
     } 
     // I'm not sure how to give the Map back to main. 
    } 
} 

올바른 접근 방식을 취하고 있는지 확실하지 않습니다. 또한 매퍼 스레드를 종료하고 기본 맵을 검색하는 방법을 알지 못합니다. 여러 매퍼 스레드가 있지만 위의 코드에서 하나만 인스턴스화했습니다.

또한 Parse 클래스가 스레드가 아니라 run() 메서드를 재정의하지 않으면 다른 클래스 만 인식하므로 Parse 클래스가 일종의 대기열이어야한다고 생각합니다.

아이디어가 있습니까? 감사.

편집 : 답장을 보내 주셔서 감사합니다. I/O가 주요 병목 지점이 될 것이므로이를 병렬화하면 효율성 이점이 거의 없을 것으로 보입니다. 그러나 데모 용으로 올바른 방향으로 가고 있습니까? 나는 멀티 스레딩을 사용하는 방법을 알지 못해서 약간 괴롭다.

+7

파일에서 읽는 것이 코드 병목 목입니다. 멀티 스레딩은 여기서 도움이되지 않습니다. –

+1

멀티 스레딩을 사용하면 여기에서 발을 쏠 수 있습니다. @HovercraftFullOfEels가 지적한 것처럼 스레드가 디스크 IO 속도보다 훨씬 빠르게 실행될 수 있습니다. 어떤 스레드가 얼마나 많은 행을 읽었는지 어떻게 관리 할 계획입니까? 예기치 않은 이유로 하나 이상의 스레드가 실패하면 어떻게됩니까? 하나의 스레드에서 하나의 파일을 처리하고 현재 사용중인 컴퓨터를 기반으로하는 처리 방법을 선택하는 것이 좋습니다. 128 기가 램이 장착 된 서버를 가지고 있다면 메모리에 읽어 와서 한 라인 씩 처리하지 않으면 처리하십시오. – JVXR

답변

2

자주 I/O가 메모리 내 작업보다 훨씬 오래 걸립니다. 우리는 I/O-bound과 같은 작업을 참조합니다. 평행주의는 기껏해야 한계 개선이있을 수 있으며 실제로 상황을 악화시킬 수 있습니다.

지도에 무언가를 넣으려면 다른 스레드가 필요하지 않습니다. 파싱이 비정상적으로 비싸지 않는 한, 다른 스레드를 필요로하지 않습니다.

이러한 작업을 수행하는 다른 스레드가있는 경우 다음 줄을 읽는 것을 기다리는 데 시간을 할애 할 수 있습니다.

I/O를 병렬화해도 반드시 도움이되는 것은 아니며 상처를 줄 수도 있습니다. CPU가 병렬 스레드를 지원하는 경우에도 하드 드라이브가 병렬 읽기를 지원하지 않을 수 있습니다.

편집 :

이 작업이 아마 I/O가 결합 된이었다 가정에 댓글을 우리 모두 - 그 자주 사실 때문이다. 그러나 아래의 의견에서이 사례는 예외로 판명되었습니다. 더 좋은 대답은 아래의 네 번째 주석을 포함했을 것입니다 :

파일의 모든 라인을 처리하지 않고 읽는 데 걸리는 시간을 측정합니다. 읽기와 처리에 걸리는 시간과 비교하십시오. 그렇게하면 얼마나 많은 시간을 절약 할 수 있는지에 대한 상한선이 생깁니다. 이것은 스레드 동기화에 대한 새로운 비용으로 인해 감소 될 수 있습니다.

+0

그래서 순차적으로 최선을 다할 것입니까? – dman33

+0

읽기와 처리를 두 개의 스레드로 분리하여 약간의 개선이 있었다면 개발 시간/위험이 더 많이 들고 관리하기가 더 복잡한 코드를 사용하여 작을 수 있습니다. 즉, 하드 디스크 드라이브에 대한 우리의 언급이 SSD (Solid-State Drive)에 어떻게 적용되는지 확신 할 수 없습니다. SSD를 사용하여 읽기를 병렬 처리하는 것에 대해 의견이있는 사람은 누구입니까? –

+0

데모 용으로 위의 방법으로 개선 할 수있는 점은 무엇입니까? 나는 그것이 많은 도움이되지 않을 것이고, 특히 생산 코드에있어서 문제가되지는 않을 것이라고 생각하지만, 여전히 궁금하다. – dman33

6

왜 여러 개의 스레드가 필요합니까? 디스크가 하나 뿐이므로 너무 빨리 갈 수 있습니다. 멀티 스레딩은이 경우 거의 확실하게 도움이되지 않습니다. 그리고 만약 그렇다면, 사용자의 관점에서 볼 때 매우 작을 것입니다. 멀티 스레딩이 문제이 아닙니다. 거대한 파일에서 읽는 것이 병 목입니다.

+0

사실, 가장 큰 병목 현상이 파일에서 확실히 읽힐 것입니다. 하나의 스레드가 IO에서 계속해서 읽는 것을 속도로 돕는 반면, 다른 스레드는 구문 분석하고 항목을지도에 넣는 데 도움이됩니까? – dman33

+0

@ dman33 : 아니요, 도움이되지 않습니다. –

+0

데모를 위해 위의 방법으로 개선 할 수있는 부분이 있습니까? 나는 그것이 많은 도움이되지 않을 것이고, 특히 생산 코드에있어서 문제가되지는 않을 것이라고 생각하지만, 여전히 궁금하다. – dman33

0

Amdahl's Law을 읽을 수도 있습니다. 대부분의 작업은 엄격하게 직렬 (IO)이므로 나머지를 멀티 스레딩하면 무시할만한 개선 효과를 얻을 수 있습니다. 확실히 다중 스레드 코드를 작성하는 비용은 들지 않습니다.

아마 새 장난감을 찾아야 병렬 처리 할 수 ​​있습니다.

+0

이 예제를 사용하기위한 특별한 필요가 있습니다. 현재 전체 프로그램을 실행하는 데 약 9000ms가 걸리고 입력 행을 한 줄씩 읽는 것만으로 800ms가됩니다. 따라서 병렬 처리를 조금만하면 개선 할 수 있다고 생각합니다. 나는 단지 하나의 독서를하는 곳과 다른 모든 것을하는 두 개의 실을 사용하는 것을 생각하고 있습니다. – dman33

+0

코드를 프로파일 링 해 보셨습니까? 최적화를 시도하기 전에 시간이 소비되고있는 곳을 찾아내는 것이 현명 할 것입니다. –

관련 문제