2012-10-02 4 views
1

제목에 스레드 기반 구조에 문제가 있습니다. 내가 뭘해야입니다 :arrayList에서 스레드 제거 및 함수 삽입

  • 하나의 스레드는 루프에서 실행 및 점검 목록에 뭔가가 존재하는 경우 등 다음 객체에 대한 몇 가지 작업을 수행하는 경우 다음 목록에서입니다

  • 기능을 제거 '외부'에서 호출하고이 목록에 새 객체를 추가합니다. 그것이 올바른 접근 방식

    public class Queue implements Runnable { 
        private List<X> listOfObjects = new ArrayList<X>; 
    
        public void addToList(X toAdd){ 
         listOfObject.add(toAdd); 
        } 
    
        public void run() { 
         while(true){ 
          synchronized(listOfObjects){ 
          if(!listOfObjects.isEmpty()){ 
           listOfObjects.get(0).doSth(); 
           listOfObjects.remove(0); 
          } 
          } 
         } 
        } 
    } 
    

    가 : 여기

내 접근 방식인가? 이 목록에 추가하는 것도 동기화해야합니까?

답변

9

시도해보고 직접 작성하지 말고 java.util.concurrent.BlockingQueue의 구현을 시도해보세요! LinkedBlockingQueue이 잘 작동 할 것으로 생각됩니다. 여러 소스에서 대기열에 항목을 쓸 수 있으며 소비자 스레드는 스레드로부터 안전한 방식으로 각 항목을 꺼서 순서대로 처리합니다. BlockingQueue에 대한 소비자 스레드가 합니다 (take() 메서드를 호출하여)을 기다립니다

참고. 그러나 위의 구현은 대기열에서 항목이 처리 될 때까지 기다리는 동안 CPU를 회전하고 소비합니다 (CPU를 사용하고 CPU 사용을 모니터하는 경우 분명합니다).

여기에 an explanatory article입니다.

+0

처리 할 대기열이 길면 어떻게됩니까? 모든 요소가 처리 될 때까지 새 요소를 추가합니까? – xwhyz

+0

대기열이 가득 차면 생성자에서 크기를 지정하고 생성자 블록에서 크기를 지정할 수 있습니다. 이를 제한된 대기열이라고합니다. –

+0

블로킹 큐의 일부 구현으로이를 구성 할 수 있다고 생각합니다. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingDeque.html (예 : –

1

당신은 모든 목록에 액세스 동기화해야합니다

public void addToList(X toAdd){ 
    synchronized(listOfObject) { 
     listOfObject.add(toAdd); 
    } 
} 

은 또한 당신이 모든 synchronized 블록을 제거 할 수있는 경우 목록의 스레드 안전 구현 이러한 CopyOnWriteArrayList을 사용할 수 있습니다.

ps : 다른 대답에서 언급했듯이 ArrayBlockingQueue을 다시 구현하는 것으로 보입니다.

1

수동으로 동기화 된 블록 대신 Collections.synchronizedList() 래퍼를 사용하는 것이 좋습니다.

1

추가 된 요소를 처리 할 스레드의 대기열을 만들려고하는 것 같습니다.

더 간단한 방법은 ExecutorService를 사용하는 것입니다.

ExecutorService service = Executors.newSingleThreadedPool(); 

// to add a task. 
service.submit(new Runnable() { 
    public void run() { 
     // process X here 
    } 
}); 
관련 문제