2012-08-06 5 views
0

매우 기본적인 초보자 용 코드가 있습니다. 링크 된 블로킹 큐 내에있는 작업자 개체 풀을 호출합니다. 이 코드는 작업자 개체를 다시 사이클링하여 입력 데이터를 인쇄합니다. ;) (시점에서 현재 = (quoteworkerobject) idlechannels.take -LinkedBlockingQueue의 교착 상태 (?)

public class throttleheapthreadpool{ 
      private quoteworkerobject[] channels; 
      private LinkedBlockingQueue<quoteworkerobject> idlechannels; 
      public throttleheapthreadpool(int poolsize,int stocks){ 
     channels=new quoteworkerobject[poolsize]; 
     idlechannels=new LinkedBlockingQueue<quoteworkerobject>(); 

     for(int i=1;i<poolsize;i++){ 
      channels[i]=new quoteworkerobject(idlechannels); 
      idlechannels.add(channels[i]);//All WORKERS to Idle pool to start 
     } 
    } 

    public void execute(Integer quote){ 
     quoteworkerobject current = null; 
     try { 
         //extract worker from pool 
      current = (quoteworkerobject)idlechannels.take(); 
      current.put(quote); 
     } catch (InterruptedException e) { 
     } 
    } 

    class quoteworkerobject{ 
     LinkedBlockingQueue<Integer> taskqueue=new LinkedBlockingQueue<Integer>(); 
     Thread quotethread=null; 
     LinkedBlockingQueue<quoteworkerobject> idle=null; 
     @SuppressWarnings("unchecked") 
     public quoteworkerobject(LinkedBlockingQueue<quoteworkerobject> idlechannels){ 
      this.idle=idlechannels; 
      Runnable r=new Runnable(){ 
       public void run() { 
        insertquote(); 
       } 
      }; 
      quotethread=new Thread(r); 
      quotethread.start();//spawn a thread from the worker 
     } 
     public void put(Integer quote){ 
      taskqueue.add(quote); 
     } 
     public void insertquote(){ 
      try{ 
       Integer thisquote=taskqueue.take(); 
       idle.add(this); 
      } 
      catch(Exception ex){ 
      } 

     } 

    } 

    public static void main(String[] args){ 
     throttleheapthreadpool pool=new throttleheapthreadpool(5,200); 
     Random randomGenerator = new Random(); 

     for(int node=0;node < 20;node++){ 
      int d=randomGenerator.nextInt(5*200); 
      pool.execute(d); 
     } 
    } 

} 

지속적 8 실행에 동결이 코드는 :

나는 다음과 같이 동결/일관성 교착 상태를 찾을 수

위의 오류는 무엇입니까?

+0

풀 크기를 5에서 20으로 변경하면 도움이됩니까? – scientiaesthete

+0

@RanadhirNag가 투표를하거나 당신이 원하는 답변을 수락하십시오. ;) – Eugene

답변

1

내 리팩터링을 참조하십시오 (여전히 완벽하지는 않지만 약간 더 읽기 쉽습니다). 다음과 같이 문제가 :

  • 당신은 (throttleheapthreadpool의 생성자에서 1부터 5까지 루프) 4 명 근로자를 만들
  • 각 근로자는 별도의 스레드에서 번 insertquote를 실행하고 유휴 풀
  • 로 돌아갑니다

전체적으로 작업이 완료된 4 개의 작업을 제출하고 작업자가 대기열로 돌아 오면 작업을 소비하지 않는다는 것을 제외하고는 추가로 4 개의 작업 (총 8 개)을 제공합니다. insertquote 메서드가 종료되었습니다.

해결 방법 : 실행 insertquote 동안 루프 : 여기에 코드 내 현재 버전 정보

public void insertquote() { 
    try { 
     while (true) { 
      taskqueue.take(); 
      idle.add(this); 
     } 
    } catch (Exception ex) { 
    } 
} 

이다 : 나는 (? 싫어) 왜

public class ThrottleHeapThreadPool { 

    private final BlockingQueue<QuoteWorkerObject> idlechannels = new LinkedBlockingQueue<QuoteWorkerObject>(); 

    public static void main(String[] args) { 
     ThrottleHeapThreadPool pool = new ThrottleHeapThreadPool(5, 200); 
     Random randomGenerator = new Random(); 

     for (int node = 0; node < 20; node++) { 
      int d = randomGenerator.nextInt(5 * 200); 
      pool.execute(d); 
     } 
    } 

    public ThrottleHeapThreadPool(int poolsize, int stocks) { 

     for (int i = 1; i < poolsize; i++) { 
      QuoteWorkerObject worker = new QuoteWorkerObject(idlechannels); 
      idlechannels.add(worker);//All WORKERS to Idle pool to start 
      worker.init(); 
     } 
    } 

    public void execute(Integer quote) { 
     try { 
      //extract worker from pool 
      QuoteWorkerObject worker = idlechannels.take(); 
      worker.put(quote); 
     } catch (InterruptedException e) { 
     } 
    } 

    class QuoteWorkerObject { 

     private final BlockingQueue<Integer> taskqueue = new LinkedBlockingQueue<Integer>(); 
     private final BlockingQueue<QuoteWorkerObject> idle; 

     @SuppressWarnings("unchecked") 
     public QuoteWorkerObject(BlockingQueue<QuoteWorkerObject> idlechannels) { 
      this.idle = idlechannels; 
     } 

     public void init() { 
      new Thread(new Runnable() { 
       public void run() { 
        insertquote(); 
       } 
      }).start(); 
     } 

     public void put(Integer quote) { 
      taskqueue.add(quote); 
     } 

     public void insertquote() { 
      try { 
       while (true) { 
        taskqueue.take(); 
        idle.add(this); 
       } 
      } catch (Exception ex) { 
      } 
     } 
    } 
} 
2

이 정확히 그렇게하지 그러한 코드를 사용하는 것을 좋아합니다. 당신은/우리의 삶을 더 쉽게 만들고 몇 달 후에도 그것을보고 증명할 수있는 코드를 작성해야합니다 : 그에 따라 변수 이름을 지정하고 짧은 문서 나 설명 등을 작성하십시오. 내가 무슨 일이 일어나는지 이해할 수 없기 때문에 리팩터링하는 데 25 분이 걸렸다.

작은 리팩터링을 추가했고 몇 개의 중단 점을 추가하여 코드를 살펴 보았습니다. 설명은 내부에 있습니다. 하지만 문제는 insertQuote 메서드에 있습니다. 너무 일찍 끝납니다.

import java.util.Random; 
import java.util.concurrent.LinkedBlockingQueue; 

public class Pool { 
private Worker[] workers; 
private LinkedBlockingQueue<Worker> workerQueue; 



/** 
* Create a pool of 5 workers and a {@link LinkedBlockingQueue} to store them 
*/ 
public Pool(int poolsize) { 
    //1. First you get here : you create a Pool of 5 Worker Threads and a Queue to store them 
    System.out.println("1."); 
    workers = new Worker[poolsize]; 
    workerQueue = new LinkedBlockingQueue<Worker>(); 

    for (int i = 0; i < poolsize; i++) { 
     //2. You instantiate 5 worker Threads and place each of them on the Queue 
     System.out.println("2."); 
     workers[i] = new Worker(workerQueue); 
     workerQueue.add(workers[i]); 
    } 
} 

public void execute(Integer quote) { 
    Worker current = null; 
    try { 
     // extract worker from pool 
     //6. Get a worker from the Queue 
     System.out.println("6."); 
     current = workerQueue.take(); 
     current.put(quote); 
    } catch (InterruptedException e) { 
    } 
} 


/** 
* 
* 
*/ 
class Worker { 
    LinkedBlockingQueue<Integer> taskqueueForEachWorker = new LinkedBlockingQueue<Integer>(); 
    LinkedBlockingQueue<Worker> workerQueue = null; 

    public Worker(LinkedBlockingQueue<Worker> idlechannels) { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       //3. You call the insert quote method 
       System.out.println("3."); 
       insertquote(); 
      } 
     }).start(); 
    } 

    public void put(Integer quote) { 
     //7. Add a task for each Thread to do 
     System.out.println("7."); 
     taskqueueForEachWorker.add(quote); 
    } 

    //TODO The problem is here: After you execute this line : workerQueue.add(this); this method ends, NO MORE worker Threads are put on the queue, 
    // thus at point 6 you block, well because there are no more worker Threads an no one add them. 

    public void insertquote() { 
     try { 
      // 4. You try to take an Integer from the Pool of tasks from rach Thread, but there is nothing yet - it is empty, thus each Thread (worker) 
      // blocks here, waiting for a task 
      System.out.println("4."); 
      Integer thisquote = taskqueueForEachWorker.take(); // This will successed only after 7. 
      workerQueue.add(this); 
     } catch (Exception ex) { 
     } 
    } 
} 

public static void main(String[] args) { 
    Pool pool = new Pool(5); 
    Random randomGenerator = new Random(); 

    for (int node = 0; node < 20; node++) { 
     int d = randomGenerator.nextInt(5 * 200); 
     System.out.println("5."); 
     pool.execute(d); 
    } 
} 

}

는 출력 1 2. 3. 4. 2. 3. 4. 2. 3. 4. 2 될 것이다. 3. 4. 2. 3. 4. 5. 6. 7. 6. 7. 5. 6. 7. 제 제 5. 6. 516, 5. 6. 7. . 6.

최종 행이 6임을 확인하십시오. insertQuote 메소드가 종료되어 대기열이 비어있어 여기에 블록이 있으면 작업자 스레드가 모두 사용되었습니다.

또한 작업자 스레드가 각각 분리 된 대기열을 사용하기 때문에 "작업 도용"패턴을 구현해야하거나 데크을 구현해야합니다. 그것도보십시오.