0

この下の質問を重複したものとして扱わないでください..!

マルチスレッドを一度に 1 つずつ順番に実行できるようにするクラスを開発しました。このクラスの claimAccess 関数と release Access 関数の間のすべてのアプリケーション コードは、一度に 1 つのスレッドでのみ実行されます。他のすべてのスレッドは、前のスレッドが完了するまでキューで待機します。今、エグゼキュータ、サイクルバリア、カウントダウンラッチなどの他の手段でこれと同じことを達成できるかアドバイスしてください..!!他のアプローチでこれを構築する方法を提案してください

import java.util.ArrayList;
import java.util.List;

public class AccessGate {
    protected boolean shouldWait = false;
    protected final List waitThreadQueue = new ArrayList();

    /**
     * For a thread to determine if it should wait. It it is, the thread will
     * wait until notified.
     * 
     */
    public void claimAccess() {
        final Thread thread = getWaitThread();
        if (thread != null) {
            // let the thread wait untill notified
            synchronized (thread) {
                try {
                    thread.wait();
                } catch (InterruptedException exp) {
                }
            }
        }
    }

    /**
     * For a thread to determine if it should wait. It it is, the thread will be
     * put into the waitThreadQueue to wait.
     * 
     */
    private synchronized Thread getWaitThread() {
        Thread thread = null;
        if (shouldWait || !waitThreadQueue.isEmpty()) {
            thread = Thread.currentThread();
            waitThreadQueue.add(thread);
        }
        shouldWait = true;
        return thread;
    }

    /**
     * Release the thread in the first position of the waitThreadQueue.
     * 
     */
    public synchronized void releaseAccess() {
        if (waitThreadQueue.isEmpty()) {
            shouldWait = false;
        } else {
            shouldWait = true;
            // give the claimAccess function a little time to complete
            try {
                Thread.sleep(10);
            } catch (InterruptedException exp) {
            }

            // release the waiting thread
            final Thread thread = (Thread) waitThreadQueue.remove(0);
            synchronized (thread) {
                thread.notifyAll();
            }
        }
    }
}
4

2 に答える 2

2

はい、これを行うためのより簡単な方法があります。最も単純なのは、モニターを使用することであり、待機、睡眠、またはその他の問題はありません。

// somewhere visible
public final Object accessGate = new Object();

// in your application code
synchronized (accessGate) {
    // this block will be executed only in one thread at one time
}

Javaの組み込みモニターは、必要なセマンティクスをほぼ提供します。唯一の問題は、スレッドがロックを保持する順序が保証されていないことです。これは、基盤となるオペレーティングシステムがロック(セマフォやミューテックスなど)の順序を処理する方法にかかっています。オペレーティングシステムは必要な動作を保証する可能性がありますが、これは一般的に移植性がありません。

ポータブルな注文保証が必要な場合は、いくつかの選択肢があります。最も明白なのは、ReentrantLock公平性がtrueに設定されていることです。

// somewhere visible
public final Lock accessGate = new ReentrantLock(true);

// in your application code
accessGate.lock();
try {
    // this block will be executed only in one thread at one time
}
finally {
    accessGate.unlock();
}

もう1つはSemaphore、単一の許可と公平性がtrueに設定されているaです。

// somewhere visible
public final Semaphore accessGate = new Semaphore(1, true);

// in your application code
accessGate.acquire();
try {
    // this block will be executed only in one thread at one time
}
finally {
    accessGate.release();
}

これら2つの動作は非常に似ています。

于 2012-12-09T09:52:28.030 に答える
2

これはExecutorService

Executors.singleThreadExecutor()は、一度に 1 つのタスクを実行し、順番に実行します。

Executor無制限のキューで動作する単一のワーカー スレッドを使用する を作成します。(ただし、シャットダウン前の実行中に障害が発生してこの単一のスレッドが終了した場合、後続のタスクを実行するために必要に応じて新しいスレッドが代わりに使用されることに注意してください。) タスクは 順次実行されることが保証されており、複数のタスクがアクティブになることはありません。いつでも。

于 2012-12-09T09:05:10.857 に答える