1

マルチスレッド コードは、リソース (ファイル システムなど) に非同期的にアクセスします。

これを実現するために、条件変数を使用します。FileSystemが次のようなインターフェースであるとします。

class FileSystem {
    // sends a read request to the fileSystem
    read(String fileName) {
        // ...
        // upon completion, execute a callback
        callback(returnCode, buffer);
    }
}

にアクセスするアプリケーションができましたFileSystemreadFile()メソッドを介して複数の読み取りを発行できるとします。オペレーションは、渡されたバイト バッファにデータを書き込む必要があります。

// constructor
public Test() {
    FileSystem disk = ...
    boolean readReady = ...
    Lock lock = ...

    Condition responseReady = lock.newCondition();
}

// the read file method in quesiton
public void readFile(String file) {
    try {
        lock.lock(); // lets imagine this operation needs a lock

        // this operation may take a while to complete; 
        // but the method should return immediately
        disk.read(file); 

        while (!readReady) { // <<< THIS
            responseReady.awaitUninterruptibly();
        }
    } 
    finally {
        lock.unlock();
    }
}

public void callback(int returnCode, byte[] buffer) {
    // other code snipped...

    readReady = true;  // <<< AND THIS
    responseReady.signal();
}

これは条件変数を使用する正しい方法ですか? readFile()すぐに戻りますか?

(読み取りにロックを使用するのはばかげていることは知っていますが、ファイルへの書き込みもオプションです。)

4

1 に答える 1

1

あなたの質問には多くのことが欠けています (つまり、スレッドについての具体的な言及はありません) が、とにかく答えようとします。

ロック変数も条件変数も、バックグラウンド機能を提供しません。これらは、スレッドが他のスレッドからのシグナルを待機するために使用されるだけです。言及していませんが、disk.read(file)メソッドはスレッドを生成してIOを実行し、すぐに戻ることができますが、呼び出し元はreadReadyとにかくループに座ってしまい、無意味に見えます。呼び出し元が待機する必要がある場合は、IO 自体を実行できます。

より良いパターンは、Java 5 Executors サービスのようなものを使用することです。

 ExecutorService pool = Executors.newFixedThreadPool(int numThreads);

pool.submit(Callable)次に、別のスレッドでバックグラウンドで実行されるジョブをサブミットする which を呼び出すことができます (プールに次に使用可能なスレッドがある場合)。Submit はFuture、バックグラウンド タスクが終了したかどうかを調査するために呼び出し元が使用できる を返します。結果オブジェクトを返すこともできます。並行クラスは、ロックおよび条件付きシグナル/待機ロジックを処理します。

お役に立てれば。

psまた、readReady同期されていないため、揮発性にする必要があります。

于 2010-11-17T03:06:44.197 に答える