繁体   English   中英

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

[英]How to check if a thread is running in the ExecutorService Thread pool

我如何检查一个线程是否在线程ExecutorService池中运行?

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

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

谢谢!

你需要使用Semaphore

这允许您有许多“许可”来做工作。 如果你只想要一个任务同时运行,那么有一个Semaphore有一个许可证,否则有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() - 但我想你知道这个并且由于某种原因不能。

编辑

我捅了一下,看看这是否可以整理,我遇到了这个 这提示了一个更简洁的解决方案:

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);
}

我如何检查一个线程是否在线程ExecutorService池中运行?

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

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.
}

简而言之,你没有。 执行者不应该以这种方式使用。 如果要手动管理线程,请在没有Executors的情况下执行。 如果使用Executors,请将思路从Thread s转移到Runnable 使用java.util.concurrent同步或任何高级抽象,使您的Runnables或类和方法是线程安全的。

我如何检查一个线程是否在线程ExecutorService池中运行?

这在ExecutorService线程池的上下文中没有意义。 该池正在执行Runnable (或Callable )类。 也许您应该问的是,您是否可以查看特定作业是否在池中运行。

如果要完成此操作,则run() (或call() )方法前面的每个作业都可以检查某种synchronized对象,并根据需要等待或继续。 也可能是您可以拥有多个线程池并将作业分成更小的部分,这样您就可以控制作业的哪些部分同时运行。

但是,正如@Ralf指出的那样,你正在做的是反对线程池的整个点。 线程池的重点是作业以异步方式运行。 如果你需要很多同步点,那么你可能需要重新设计。

如果您提供有关您的环境的更多详细信息,我们可以更具体地解决您的基本问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM