2013-03-09 4 views
0

여러 스레드와 동기화를 사용하는 방법을 찾고 있습니다. wait() 및 notify()를 사용하여 시도했지만 스레드가 여전히 동기화되지 않습니다. 큰 프로젝트가 있지만 간단히 말해 setter 메서드 (이 경우에는 thread1)로 미리 지정된 횟수만큼 스레드를 실행하고 각 "set"후에 getter 메서드 (thread2)를 실행하여 객체를 가져옵니다. 다른 많은 예를 살펴 보았지만 제대로 작동하지 않는 것 같습니다. 따라서 이것이 도움이되지 않는 이유에 대한 도움이나 설명이 도움이 될 것입니다.1 클래스의 동기화 된 스레드

가끔씩 thread1이 먼저 실행되지만 다른 몇 번 먼저 thread2가 실행되어 동기화가 작동하지 않는 경우가 있습니다.

감사합니다.

import java.util.ArrayList; 

public class ThreadTest{ 

    private ArrayList<Object> myList; 

    public ThreadTest(){ 

     myList = new ArrayList<Object>(); 

     Thread thread1 = new Thread(){ 
      public void run(){ 
       for(int i = 0; i < 10; i++){ 
        addToList("" + i); 
       } 
      } 
     }; 

     Thread thread2 = new Thread(){ 
      public void run(){ 
       for(int i = 0; i < 10; i++){ 
        System.out.print(myList.get(i) + " "); 
       } 
      } 
     }; 

     thread1.start(); 
     thread2.start(); 
    } 

    public synchronized void addToList(String a){ 
     myList.add(a); 
     notify(); 
    } 

    public synchronized ArrayList<Object> getList(){ 
     try{ 
      wait(); 
     } 
     catch (InterruptedException e){ 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return myList; 
    } 

    public static void main(String[] args){ 
     new ThreadTest(); 
    } 
} 
+0

'getList()'메소드의 목적은 무엇입니까? 당신은 그것을 사용하지 않습니다. – bsiamionau

+1

바퀴를 재발 명하지 마십시오. ['BlockingQueue'] (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html) –

+0

@ bmorris591 그러나 사각형 휠을 원하면 어떻게합니까?) –

답변

2

사용하십시오 BlockingQueue 확실히 당신에게 ExecutorService 당신이 그렇지 않으면 완료 shutdown() 당신이 프로그램을 종료하지 않습니다있어 확인 모든 Thread

public void doStuff() { 
    final Object finishSupplying = new Object(); 
    final BlockingQueue<Object> myList = new LinkedBlockingQueue<Object>(); 
    final Runnable supplier = new Runnable() { 
     public void run() { 
      for (int i = 0; i < 10; i++) { 
       myList.add(i); 
      } 
     } 
    }; 

    final Runnable consumer = new Runnable() { 
     public void run() { 
      while (true) { 
       try { 
        final Object thing = myList.take(); 
        if(thing == finishSupplying) break; 
        System.out.print(thing + " "); 
       } catch (InterruptedException ex) { 
        Thread.currentThread().interrupt(); 
       } 
      } 
     } 
    }; 

    final ExecutorService exectutorService = Executors.newFixedThreadPool(2); 
    final Future<?> supplierHandle = exectutorService.submit(supplier); 
    final Future<?> consumerHandle = exectutorService.submit(consumer); 
    try { 
     supplierHandle.get(); 
    } catch (InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } catch (ExecutionException ex) { 
     //PROBLEMS, handle 
    } 
    myList.add(finishSupplying); 
    try { 
     consumerHandle.get(); 
    } catch (InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } catch (ExecutionException ex) { 
     //PROBLEMS, handle 
    } 
} 

처리하는 ExecutorService를 사용하여 자동적으로 당신의 동기화 해 작업을 수행합니다.

1

알림을 받으면 기다릴 때 루프에서 확인해야하는 상태를 업데이트해야합니다. 이것은 대기 시작하기 전에

  • 알림 트리거로 필요하며 신호 대기가 외관상 깨울 수
  • 을 잃게됩니다.

참고 : 기다리는 것이 없기 때문에 소비 스레드가 대기하지 않습니다.

이 문제를 해결하는 데는 여러 가지 방법이 있지만 가장 좋은 해결책은이 패턴을 지원하도록 설계된 BlockingQueue를 사용하는 것입니다.

0

전체 목록에 액세스하려면 getter & setter를 사용하지 말고 요소를 밀어 넣고 끌어 당깁니다. 말했듯이 BlockingQueue은 동기화 된 목록 구현입니다.

즉, 직접 구현하려는 경우 getList를 목록의 동기화 된 remove(0)으로 바꾸십시오.이 경우 목록의 첫 번째 요소 만 반환됩니다.