9

スレッド ExecutorService のプールでスレッドが実行されているかどうかを確認するにはどうすればよいですか?

背景:
フラグが設定されている場合、スレッド プール内のスレッド間で同期したいと考えています。そのため、同期のためにフラグが true に設定されている場合は、他のスレッドが実行されているかどうかを確認するか、その完了を待ってから、ブロックしているスレッドを同期で呼び出して、他のスレッドがこのブロックしているスレッドが終了するのを待つようにする必要があります。

フラグが設定されていない場合、同期する必要はなく、スレッドを並行して実行できます。

ありがとう!

4

3 に答える 3

5

を使用する必要がありますSemaphore

これにより、作業を行うための多くの「許可」を持つことができます。一度に 1 つのタスクのみを実行するSemaphore場合は、許可を 1 つ持つ を使用します。それ以外の場合は、プール内のSemaphoreの数よりも多くの許可を使用して を使用Threadします。

static class Worker implements Runnable {

    final Semaphore semaphore;

    public Worker(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            try {
                //do stuff
            } finally {
                semaphore.release();
            }
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
    }
}

public static void main(String[] args) {

    final int numThreads = 10;
    final ExecutorService executorService = Executors.newFixedThreadPool(10);
    final Semaphore semaphore;
    boolean myflag = true;
    if (myflag) {
        semaphore = new Semaphore(1);
    } else {
        semaphore = new Semaphore(numThreads);
    }
    final Worker worker = new Worker(semaphore);
    executorService.submit(worker);
}

newSingleThreadExecutor()この例は、一度に 1 つのタスクのみを実行する必要がある場合に a を使用できるため、少し不自然です。

編集

これが整理できるかどうかを確認するために少し突っ込んだところ、これに出くわしました。これは、よりきちんとした解決策を示唆しています。

static interface TaskBlocker {

    void acquire();

    void release();
}

static class Worker implements Runnable {

    final TaskBlocker taskBlocker;

    public Worker(TaskBlocker taskBlocker) {
        this.taskBlocker = taskBlocker;
    }

    @Override
    public void run() {
        taskBlocker.acquire();
        try {
            //do stuff
        } finally {
            taskBlocker.release();
        }
    }
}

public static void main(String[] args) {

    final int numThreads = 10;
    final ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
    final TaskBlocker taskBlocker;
    boolean myflag = true;
    if (myflag) {
        taskBlocker = new TaskBlocker() {
            final Lock lock = new ReentrantLock();

            @Override
            public void acquire() {
                lock.lock();
            }

            @Override
            public void release() {
                lock.unlock();
            }
        };
    } else {
        taskBlocker = new TaskBlocker() {
            @Override
            public void acquire() {
            }

            @Override
            public void release() {
            }
        };
    }
    final Worker worker = new Worker(taskBlocker);
    executorService.submit(worker);
}
于 2013-04-12T16:56:34.633 に答える
4

要するに、あなたはしません。Executor は、そのように使用されることを意図していません。スレッドを手動で管理する場合は、Executor なしで実行してください。Executor を使用する場合は、思考をThreadsから s にシフトしますRunnable。同期または のいずれかの高レベルの抽象化を使用して、ランナブルまたはクラスとメソッドをスレッドセーフにしjava.util.concurrentます。

于 2013-04-12T16:54:32.290 に答える
3

スレッド ExecutorService のプールでスレッドが実行されているかどうかを確認するにはどうすればよいですか?

スレッドが特定の で実行されているかどうかだけを知りたい場合は、特定のExecutorServiceを使用して を作成し、特別な名前などの特別なプロパティをスレッドにアタッチすることができます。ExecutorServiceThreadFactory

private static final String EXECUTOR_THREADNAME_PREFIX = "ExecutorThread";

ThreadFactory threadFactory = new ThreadFactory() {

    private final AtomicInteger id = new AtomicInteger(0);

    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setName(EXECUTOR_THREADNAME_PREFIX + "_" + id.incrementAndGet());
        return thread;
    }
};

myExecutor = Executors.newCachedThreadPool(threadFactory);

次に、スレッドで、名前がプレフィックスで始まるかどうかを確認します。

if (Thread.currentThread().getName().startsWith(EXECUTOR_THREADNAME_PREFIX)) {
    // In executor.
} else {
    // Not in executor.
}
于 2014-02-21T19:49:25.427 に答える