0

基本的に、このコードは http 要求を実行し、http 要求がタイムアウトした場合は、wifi 接続をリセットします (時々それを行う必要があります。それはまさにその通りです。「wifi をリセットする」の代わりに、Android 以外に関連するものにすることもできます。繋がり")。

次の特殊なケースを考慮する必要があります。

  • 1 つ以上のスレッドが現在 http 要求を実行している場合、別のスレッドが Wi-Fi 接続をまだリセットできないようにする
  • 1 つのスレッドが既に wifi 接続をリセットしており、別のスレッドが wifi 接続をリセットしようとしている場合は、後者のスレッドに直接送信して、代わりに http 要求を再試行します (前のスレッドが wifi のリセットを終了したとき)。
  • Wi-Fi 接続が現在リセットされているときに http 要求を実行しない
  • => 一度に 1 つのスレッドのみが wifi 接続を修正できますが、複数のスレッドが同時に http 要求を開始できます

それは私に頭痛を与えています。

これまでの私のコードは次のとおりです。何を改善できますか?

static int requestsActive = 0;
protected int requestTry = 0;
static final int maxTrys = 2;
static final ReentrantLock wifiLock = new ReentrantLock();

public void evaluate() throws Exception {
try {
    requestTry++;
    while (wifiLock.isLocked()) // no not start new http request while wifi is being fixed
        Thread.sleep(400);
    requestsActive++; //increment so that another thread that wants to fix wifi knows it has to wait
    response = httpClient.execute(requestBase);
    requestsActive--; // when == 0 wifi can be fixed if it needs to
} catch (ConnectTimeoutException e) {
    requestsActive--; //same as above (for exception case)
    if (requestTry == maxTrys)
        throw new ConnectTimeoutException("maxTrys reached");
    if (!wifiLock.tryLock()) //another thread is currently fixing wifi, no need to do it myself
        evaluate(); // ...so start a new http request
    while (requestsActive > 0) // wait until no more threads are in the http request section above
        Thread.sleep(400);
    WifiManager wifiMan = (WifiManager) App.getContext().getSystemService(Context.WIFI_SERVICE);
    resetWifi(wifiMan); //reset android wifi, nothing special
    wifiLock.unlock();
    evaluate();
}
4

1 に答える 1

1

残念ながら、私は Android シミュレーターをインストールしていないため、これが機能することを保証することはできません。うまくいけば、少なくとも構築するための概念として、それがあなたにとって役立つことが証明されるでしょう. 基本的に、セマフォを使用して一度に試行できるリクエストの数を制限し、接続がタイムアウトすると、セマフォのすべての許可を取得して、Wi-Fi がリセットされる間、新しいリクエストが作成されるのをブロックします。これは、Java コード ベースに既に存在する同時実行コードを活用するため、自分で再実装する必要はありません。

セマフォの JavaDoc はこちらでご覧いただけます

static final int MAX_CONCURRENT_REQUESTS = 10;
static final Semaphore httpRequestsLock = new Semaphore(MAX_CONCURRENT_REQUESTS, true);

public void evaluate() throws Exception {
    Foo requestBase = null;
    HttpClient httpClient = new HttpClient();

    httpRequestsLock.acquire();
    try{
        response = httpClient.execute(requestBase);
    }
    catch (ConnectTimeoutException e) {
        httpRequestsLock.release();
        httpRequestsLock.acquire(MAX_CONCURRENT_REQUESTS); // Blocks until all current requests are done
        WifiManager wifiMan = (WifiManager) App.getContext().getSystemService(Context.WIFI_SERVICE);
        resetWifi(wifiMan); //reset android wifi, nothing special
        httpRequestsLock.release(MAX_CONCURRENT_REQUESTS);
        evaluate();
    }
}
于 2013-01-06T21:25:29.323 に答える