1

ベローはデフォルトの PicassoExecutorService.java で、ネットから (および以前にロードされた場合は http キャッシュから) ビットマップを要求するだけです。たとえば、100 のタスクがあり、95 がキャッシュにロードされ、5 がネットからロードされた場合、キューの最初の 5 に 5 が含まれている場合、5 枚の画像がロードされたときに 95 の画像は表示されません。それで、PicassoExecutorService.java を変更したいのですが、ExecutorService で新しいスレッドを作成して、ディスク キャッシュ フェッチ ジョブを実行することは可能ですか? 新しいキューを作成する必要がありますか?私は Java スレッド コーディングの経験があまりないので、あなたの助けが必要です。

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();
    }
  }
4

1 に答える 1

2

このクラスPicassoExecutorServiceは、接続タイプのスレッド数を調整するエグゼキュータ サービスの実装です。つまり、2G の場合、2G は遅く、4 つの同時スレッドを設定すると接続が使い果たされるため、1 つのスレッドが選択されます。

あなたが直面している問題は、キャッシュされていないジョブの一部がキャッシュされたリクエストよりも先に進んでいるためです。

ここで、ジョブがキャッシュされているかどうかを判断できる場合は、ディスク ジョブ用に別のサービスまたはスレッドを作成するだけです。あなたが示したスレッドプールは、接続タイプに基づいてリソースを制限する接続スレッドです。問題を混同して、ディスク ジョブ用に別のスレッド プールを作成しないことをお勧めします。

インターネットから取得する前にジョブがキャッシュされているかどうかわからない場合は、非常に洗練された戦略で回答を更新します。

アップデート

戦略。

まず、すべてのデバイスでのディスク読み取りタイムアウトを把握する必要があります。95 パーセンタイルのタイムアウト値が必要です。たとえば、最大値より小さい値です。したがって、1ms、2ms、1ms、50ms、20ms、3ms がある場合は、20ms または 50ms を選択しません。ディスク読み取りの場合は 3ms とします。平均 (またはより良い中央値) の接続タイムアウトは、100 ~ 500 ミリ秒のように、はるかに大きくする必要があります。

したがって、最初に、この短いタイムアウトで 10 ~ 20 スレッドのスレッド プールにジョブを送信することをお勧めします。したがって、すべての遅いジョブを除外します。

次のステップは、遅いジョブを終了することです。これは、接続が中断可能かどうかによって異なります。そうでない場合は、別の問題です。

この後、遅いジョブを接続スレッド プールに再送信するだけです。以上です。

于 2013-10-28T08:36:19.703 に答える