2014-02-18 202 views
0

我是線程新手。我搜索了許多與我的問題有關的問題,但我無法爲我找到合適的解決方案。我正在做的是我正在使用四個異步任務來使用THREAD_POOL_EXECUTOR從四個不同的社交媒體中獲取數據。代碼如下: 等待線程池完成執行

new Fb().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
new Twitter().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
... 

mAdapter = new MyAdapter(getActivity(), 
       (ArrayList<Model>) showList); 
mListView.setAdapter(mAdapter); 

我希望調用是並行的,以節省獲取數據的時間。現在我的想法是,我希望所有四個線程完成工作,然後我想按照時間戳顯示排序後的數據。現在問題是我的setAdapter在四個線程完成抓取數據之前被調用,因爲在UI線程上設置了適配器。我想要一個機制來阻塞UI線程,直到所有四個線程完成獲取數據。

我發現,也許我可以用shutdown()和ExecutorService的的awaitTermination()方法。無論如何,任何人都可以幫助我,這將是非常棒的。非常感謝

+0

你說得對。關閉或等待終止。如果要創建多個線程,還可以擴展線程類並創建自己的線程消息並重新使用相同的線程。也許java優化線程創建與持久線程,以避免創建的開銷,所以使用executor可以有效地awaitTermination。 –

+0

如果我正確理解AsyncTask的onPostExecute(Result)應該可以解決你的問題。一旦AsyncTask完成,它會在UI線程上調用onPostExecute。如果所有任務都已完成,您可以保留一個計數器,並且一旦完成,您可以在onPostExecute(Result)函數的列表視圖中設置適配器。 –

+0

是的,我做了類似的實現。謝謝你的幫助:) – Sagar

回答

1

我會做的是:

  1. 在您的活動創建一個空的ArrayList
  2. 通行證此ArrayList你的適配器和設置您的ListView適配器。 setAdapter方法不會影響listView - 它仍然是空的,因爲列表是空的。
  3. 啓動4個AsyncTasks並獲取數據。在onPostExecute()中,將此數據添加到ArrayList並調用適配器上的notifyDatasetChanged()。

,因爲它是錯誤的,不應阻止一個UI線程。當您想要立刻顯示所有數據時,您可以製作一個簡單的計數器,只需在計數器爲4時在每個onPostExecute中製作計數器++並調用notifyDatasetChange()。

+0

這是正確的方法。阻止任何UI線程是一個非常糟糕的主意。充其量,它會讓你的應用看起來很醜,因爲所有東西都保持鎖定狀態。最糟糕的是,你會得到一個ANR錯誤。或者,您可以在每次完成適配器時更新適配器,並在適配器上調用'notifyDatasetChanged()',以便更快地將信息更新爲用戶。 – DeeV

+0

好的我明白了。我不應該想到阻止UI線程。你們都是對的。我試着按@Mark的方式告訴。 Bt發生了什麼事是我在創建時間的基礎上對數據frm facebook twitter等進行排序。因此,首先任何線程的數據都將frm設置爲其postExecute(),然後其他線程完成工作,並在排序所有數據後設置數據。所以新的數據被添加到notifyDatasetChange(),看起來有些模糊。所以我一直在想另一種方式,即1)在所有線程完成執行後纔打印數據,2)對它們進行排序3)僅將適配器設置爲最終數據一次 – Sagar

+0

您可以按我告訴過的來做。設置適配器,在每個onPostExecute()添加數據到列表中啓動所有任務並創建counter ++。創建一個方法來檢查計數器是否爲4,對列表進行排序並使用notifyDatasetChanged(您也可以在此處設置適配器,應該沒有更大的區別)。 – Mark

0

如果你與阻塞UI線程真的好嗎,試試這個:

new Fb().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
new Twitter().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
... 

AsyncTask.THREAD_POOL_EXECUTOR.shutdown(); 

while (!AsyncTask.THREAD_POOL_EXECUTOR.isTerminated()) {} 

mAdapter = new MyAdapter(getActivity(), 
       (ArrayList<Model>) showList); 
mListView.setAdapter(mAdapter); 

在大多數情況下,雖然,阻塞UI線程不是一個好主意。

+0

好的謝謝你的想法。我會嘗試你的代碼:) yeaa我也同意阻止UI線程nt是一個好主意..不管怎麼說,我很感謝你的支持 – Sagar

+0

AsyncTask.THREAD_POOL_EXECUTOR不包含方法關閉和isTerminated。它們來自ExecutorService。 – Sagar

+0

哎呀,我推測AsyncTask.THREAD_POOL_EXECUTOR是一個ExecutorService。儘管上面的代碼不一定有效,但您也許可以創建自己的ExecutorService來執行類似的操作。看起來你已經接受了答案。 – benjammin

0

我可以成功處理該問題,而無需深入研究線程。我使用了執行每個線程後使布爾值爲真的簡單概念。而在UI線程我檢查infinte時間即

while(true) 
{ 
    if(flag1 && flag2 && flag3 && flag4) 
    { 
     //set the adapter and make the flags false 
     break; 
    } 

} 

不要忘記將falgs假執行,否則將繼續無限期的時間。