2013-10-28 80 views
1

bellow是默認的PicassoExecutorService.java,它只是從網絡(如果加載之前從http緩存,請求位圖)請求位圖。比方說,如果有100個任務,並且95被加載到緩存中,並且5來自網絡,如果隊列的前5箇中有5個,則當加載5個圖片時,95圖像將不會顯示。所以,我想更改PicassoExecutorService.java,我想知道是否有可能在ExecutorService中創建一個新線程來執行磁盤緩存獲取作業?我應該創建一個新的隊列嗎?我沒有那麼多的Java線程編碼,所以我需要你的幫助,thaks。ThreadPoolExecutor爲不同的任務

class PicassoExecutorService extends ThreadPoolExecutor { 
    private static final int DEFAULT_THREAD_COUNT = 3; 

    PicassoExecutorService() { 
    super(DEFAULT_THREAD_COUNT, DEFAULT_THREAD_COUNT, 0, TimeUnit.MILLISECONDS, 
     new LinkedBlockingQueue<Runnable>(), new Utils.PicassoThreadFactory()); 
    } 

    void adjustThreadCount(NetworkInfo info) { 
    if (info == null || !info.isConnectedOrConnecting()) { 
     setThreadCount(DEFAULT_THREAD_COUNT); 
     return; 
    } 
    switch (info.getType()) { 
     case ConnectivityManager.TYPE_WIFI: 
     case ConnectivityManager.TYPE_WIMAX: 
     case ConnectivityManager.TYPE_ETHERNET: 
     setThreadCount(4); 
     break; 
     case ConnectivityManager.TYPE_MOBILE: 
     switch (info.getSubtype()) { 
      case TelephonyManager.NETWORK_TYPE_LTE: // 4G 
      case TelephonyManager.NETWORK_TYPE_HSPAP: 
      case TelephonyManager.NETWORK_TYPE_EHRPD: 
      setThreadCount(3); 
      break; 
      case TelephonyManager.NETWORK_TYPE_UMTS: // 3G 
      case TelephonyManager.NETWORK_TYPE_CDMA: 
      case TelephonyManager.NETWORK_TYPE_EVDO_0: 
      case TelephonyManager.NETWORK_TYPE_EVDO_A: 
      case TelephonyManager.NETWORK_TYPE_EVDO_B: 
      setThreadCount(2); 
      break; 
      case TelephonyManager.NETWORK_TYPE_GPRS: // 2G 
      case TelephonyManager.NETWORK_TYPE_EDGE: 
      setThreadCount(1); 
      break; 
      default: 
      setThreadCount(DEFAULT_THREAD_COUNT); 
     } 
     break; 
     default: 
     setThreadCount(DEFAULT_THREAD_COUNT); 
    } 
    } 

    private void setThreadCount(int threadCount) { 
    setCorePoolSize(threadCount); 
    setMaximumPoolSize(threadCount); 
    } 
} 



    static class PicassoThreadFactory implements ThreadFactory { 
    @SuppressWarnings("NullableProblems") 
    public Thread newThread(Runnable r) { 
     return new PicassoThread(r); 
    } 
    } 

    private static class PicassoThread extends Thread { 
    public PicassoThread(Runnable r) { 
     super(r); 
    } 

    @Override public void run() { 
     Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); 
     super.run(); 
    } 
    } 
+2

無論你的'PicassoExecutorService'和你的'PicassoThread'都是反模式的最好例子:使用不必要的子類。您可以同時設置ThreadPoolExecutor的線程數和線程的優先級,而無需創建它們的子類。我可以給你的最好建議是,如果你沒有使用java線程編碼的經驗,不要限制線程的數量,也不要混淆線程優先級。那麼你沒有問題中描述的問題。在大多數情況下,您的優化是不必要的,即使不適得其反。 – Holger

+0

感謝@Holger,我認爲不要在PicassoExecutorService中執行磁盤緩存獲取,但現在我不知道如何檢查映像是否在磁盤中。我會做一些研究。 – mike

+0

@Holger好吧,邁克需要以某種方式限制移動設備同時連接的數量。 –

回答

2

PicassoExecutorService 012xx是執行器服務的實現,它調整連接類型的線程數。即對於2G它選擇1線程,因爲2G慢,並設置4個併發線程會耗盡您的連接。

您面臨的問題是因爲某些未緩存的作業超過緩存的請求。

現在,如果您能夠確定作業是否被緩存,則只需爲磁盤作業創建單獨的服務或線程即可。您向我們展示的線程池是一個連接線程,它根據連接類型限制資源。最好不要混淆擔憂併爲磁盤作業創建單獨的線程池。

如果你不能說在工作被緩存之前,試圖從互聯網上獲取它,我會用一個非常複雜的策略來更新答案。

UPDATE

策略。

首先,您需要了解所有設備上的磁盤讀取超時。您需要第95百分位超時值,例如該值小於最大值。所以如果你有1ms,2ms,1ms,50ms,20ms,3ms,你不會選擇20ms或50ms。讓磁盤讀取爲3ms。您的平均(或更好的中位數)連接超時應該更大 - 例如100-500毫秒。

所以這個想法是首先提交你的工作到一個線程池像10-20線程與這個小超時。因此它會過濾掉所有慢速作業。

下一步是終止慢速作業。這取決於您的連接是否可以中斷。如果不是,這是一個不同的問題。

之後,您只需將慢速作業重新提交給連接線程池。就是這樣。

+0

我想看到複雜的策略,目前我不知道這份工作是否緩存,是由畢加索完成的。 – mike

+0

我認爲1線程是好的,就像PicassoExecutorService一樣,2G的線程數是1(用於磁盤提取和網絡提取)。作爲文件在磁盤中,我認爲不會有超時,因爲我們最終會得到該文件。 – mike

相關問題