2012-11-22 2 views
1

내 멀티 스레드 응용 프로그램에 여러 스레드를 만드는 기본 클래스가 있습니다. 메인 클래스는 일부 스레드를 시작한 후에 기다립니다. 내가 만든 실행 가능한 클래스는 파일 목록을 가져오고, 파일을 가져오고, 웹 서비스를 호출하여 파일을 제거합니다. 쓰레드가 끝나면 메인 클래스에 다시 실행하도록 알린다. 내 문제는 잠시 동안 작동하지만 아마도 1 시간 정도 지나면 로그에서 볼 수있는 출력에서 ​​run 메소드의 맨 아래로 갈 것입니다. Java 프로세스가 아직 실행 중이지만 로그에서보고있는 내용을 기반으로 아무 것도 수행하지 않습니다.왜 멀티 스레드 응용 프로그램이 일시 중지 되었습니까?

메인 클래스 메소드 :

Main 메서드

while (true) { 

    // Removed the code here, it was just calling a web service to get a list of companies 

    // Removed code here was creating the threads and calling the start method for threads 

    mainClassInstance.waitMainClass(); 
} 

public final synchronized void waitMainClass() throws Exception { 
//  synchronized (this) { 
      this.wait(); 
//  } 
} 

public final synchronized void notifyMainClass() throws Exception { 
//  synchronized (this) { 
      this.notify(); 
//  } 
} 

나는 원래 인스턴스에서 동기화를했지만 방법으로 변경되었습니다. 또한 웹 서비스 로그 또는 클라이언트 로그에 오류가 기록되지 않습니다. 내 가정은 기다렸다가 잘못 알았거나 정보가 누락되었다는 것입니다.

구동 가능한 스레드 코드 : run 메소드의 끝에서

// This is a class member variable in the runnable thread class 
mainClassInstance.notifyMainClass(); 

나는 대기를하고 내가 필요가없는 실행하는 메인 클래스를 싶지 않기 때문에 프로세스에 알려야하는 이유 다른 스레드를 만들 수 있습니다.

메인 클래스의 목적은 스레드를 생성하는 것입니다. 클래스에는 스레드를 생성하고 마무리하는 무한 루프가 있습니다.

무한 루프의 목적은 회사 목록을 지속적으로 업데이트하기위한 것입니다.

+0

어떤 종류의 로그를 추가 했습니까? –

+0

알림은 대기중인 스레드가있는 경우에만 작동합니다. 주 스레드가 대기 상태가되지 않은 경우 알림 메시지가 표시됩니다. –

+3

세마포어로 더 잘 할 수 있습니다. –

답변

2

Java 플랫폼의 상위 수준 동시성 기능 중 하나 인 까다로운 대기/통지에서 이동하는 것이 좋습니다. ExecutorService은 아마도 필요한 기능을 제공 할 것입니다. 이의이 템플릿으로 코드를 사용하여 예를 스케치 해 봅시다 (CountDownLatch도 사용할 수 있지만, 더 배관의) : 주석 후

ExecutorService execSvc = Executors.newFixedThreadPool(THREAD_COUNT); 

while (true) { 

    // Removed the code here, it was just calling a web service to get a list of companies 
    List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>(); 
    for (Company comp:companyList) { 
     tasks.add(new FileProcessingTask(comp)); 
    } 
    List<Future<FileProcessingTask>> results = execSvc.invokeAll(tasks); // This call will block until all tasks are executed. 
    //foreach Future<FileProcessingTask> in results: check result 
} 

class FileProcessingTask implements Callable<FileResult> { // just like runnable but you can return a value -> very useful to gather results after the multi-threaded execution 
    FileResult call() {...} 
} 

------- 편집 ------

getCompanies() 호출로 모든 회사를 한 번에 제공 할 수 있고 처리 중에 해당 목록을 지속적으로 확인할 필요가없는 경우 먼저 모든 작업 항목을 작성하여이를 즉시 실행자 서비스에 제출하여 프로세스를 단순화 할 수 있습니다.

List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>(); 
    for (Company comp:companyList) { 
     tasks.add(new FileProcessingTask(comp)); 
    } 

중요한 점은 executorService는 제공된 컬렉션을 실행할 태스크의 내부 대기열로 사용한다는 것입니다. 첫 번째 작업을 수행하여 풀의 스레드에 제공하고 결과를 수집 한 다음 결과를 결과 컬렉션에 배치 한 다음 대기열에서 다음 작업을 수행합니다.

생산자/소비자 시나리오 (cfr 설명)가없는 경우, 작업이 실행 (소비)되는 동시에 새로운 작업이 생성되는 경우이 접근법은 다음 중 처리 작업을 병렬 처리하기에 충분해야합니다 간단한 방법으로 많은 스레드.

새로운 작업의 조회가 작업 처리에서 인터리브되는 이유에 대한 추가 요구 사항이있는 경우 질문에서 명확하게해야합니다.

+0

이 솔루션을 사용하면 한 스레드가 예를 들어 10 초 걸릴 수 있고 다른 스레드는 처리 할 파일 수에 따라 3 분이 걸리기 때문에 모든 스레드가 완료 될 때까지 기다리지 않으려 고합니다. – ColinMc

+0

@ user1750090 알겠습니다. 그러면 주 스레드를 깨우는 역할은 무엇입니까? 새로운 작업을하고 새로운 스레드를 시작하려면 더 많은 작업을 찾으십니까? 여러 스레드가 그 작업을 처리하는 동안 스레드가 수행 할 작업을 찾고있는 것처럼 보입니까? – maasg

+0

주 스레드를 깨우는 역할은 완료 될 때 더 많은 스레드를 만드는 것입니다. 기본적으로 회사 당 스레드를 만들어 파일을 처리하고 회사가 완료되면 주 스레드로 돌아가서 처리 할 다른 회사 스레드를 만듭니다. 다중 스레드가 작업을 처리하는 동안 작업을 찾고있는 스레드가 없습니다. 내가 가지고있는 유일한 스레드는 회사 스레드를 생성하는 주 스레드와 파일 처리를 수행하는 회사 스레드입니다. – ColinMc

관련 문제