2017-04-05 58 views
0

我正在使用BlockingQueue和ExecutorService編寫作業隊列。它基本上等待隊列中的新數據,如果有任何數據放入隊列,executorService將從隊列中提取數據。但問題是我正在使用循環等待隊列有數據,因此CPU使用率超高。 我是新來使用這個api。不知道如何改善這一點。如何優雅地等待作業任務在BlockingQueue中完成java

ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); 
BlockingQueue<T> mBlockingQueue = new ArrayBlockingQueue(); 

public void handleRequests() { 
     Future<T> future = mExecutorService.submit(new WorkerHandler(mBlockingQueue, mQueueState)); 
     try { 
       value = future.get(); 
     } catch (InterruptedException | ExecutionException e) { 
       e.printStackTrace(); 
     } 
     if (mListener != null && returnedValue != null) { 
       mListener.onNewItemDequeued(value); 
     } 
    } 
} 

private static class WorkerHandler<T> implements Callable<T> { 

    private final BlockingQueue<T> mBlockingQueue; 
    private PollingQueueState mQueueState; 

    PollingRequestHandler(BlockingQueue<T> blockingQueue, PollingQueueState state) { 
     mBlockingQueue = blockingQueue; 
     mQueueState = state; 
    } 

    @Override 
    public T call() throws Exception { 
     T value = null; 
     while (true) { // problem is here, this loop takes full cpu usage if queue is empty 
      if (mBlockingQueue.isEmpty()) { 
       mQueueState = PollingQueueState.WAITING; 
      } else { 
       mQueueState = PollingQueueState.FETCHING; 
      } 
      if (mQueueState == PollingQueueState.FETCHING) { 
       try { 
        value = mBlockingQueue.take(); 
        break; 
       } catch (InterruptedException e) { 
        Log.e(TAG, e.getMessage(), e); 
        break; 
       } 
     } 
    } 

有關如何改善這一點的任何建議將不勝感激!

+0

您的標題不會與你的問題達成一致。 – EJP

回答

1

你不需要測試隊列爲空,你只需要take(),這樣線程就會阻塞,直到數據可用。

當一個元素放在隊列中時,線程喚醒一個值被設置。

如果您不需要取消任務,你只需要:

@Override 
public T call() throws Exception { 
    T value = mBlockingQueue.take(); 
    return value; 
} 

如果你希望能夠取消任務:

@Override 
public T call() throws Exception { 
    T value = null; 
    while (value==null) { 
      try { 
       value = mBlockingQueue.poll(50L,TimeUnit.MILLISECONDS); 
       break; 
      } catch (InterruptedException e) { 
       Log.e(TAG, e.getMessage(), e); 
       break; 
      } 
    } 
    return value; 
} 
1
 if (mBlockingQueue.isEmpty()) { 
      mQueueState = PollingQueueState.WAITING; 
     } else { 
      mQueueState = PollingQueueState.FETCHING; 
     } 
     if (mQueueState == PollingQueueState.FETCHING) 

刪除這些行,break;和匹配的右大括號。

+0

注意你不需要'mQueueState'變量。您可以通過上面的邏輯直接從隊列大小中推斷出它。 – EJP

+0

對不起,我沒有看到你的答案,你的答案也是如此。我明白了,take()方法會阻塞線程,直到從隊列中提取數據爲止 – Cheng