9

如何检查线程 ExecutorService 池中是否正在运行线程?

背景:
如果设置了标志,我想在线程池中的线程之间进行同步。因此,如果该标志设置为 true 以进行同步,那么我必须检查其他线程是否正在运行或等待其完成,然后使用 synchronize 调用阻塞线程,以便其他线程等待这个阻塞线程完成。

如果未设置标志,则无需同步并且可以并行执行线程。

谢谢!

4

3 回答 3

5

您需要使用Semaphore.

这使您可以拥有许多“许可证”来工作。如果您只希望一次运行一个任务,则拥有Semaphore一个许可,否则拥有一个Semaphore许可数量大于Thread池中 s 数量的许可。

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()当您一次只需要运行一个任务时,您可以只使用 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

简而言之,你没有。执行程序不应该以这种方式使用。如果您想手动管理线程,请在没有 Executors 的情况下进行。如果您使用 Executors,请将您的想法从Threads 转移到Runnables。使用同步或java.util.concurrent.

于 2013-04-12T16:54:32.290 回答
3

如何检查线程 ExecutorService 池中是否正在运行线程?

如果您只想知道线程是否在特定的 中运行ExecutorService,您可以ExecutorService使用特定创建ThreadFactory并让它附加一些特殊属性到线程,例如特殊名称。

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 回答