如何检查线程 ExecutorService 池中是否正在运行线程?
背景:
如果设置了标志,我想在线程池中的线程之间进行同步。因此,如果该标志设置为 true 以进行同步,那么我必须检查其他线程是否正在运行或等待其完成,然后使用 synchronize 调用阻塞线程,以便其他线程等待这个阻塞线程完成。
如果未设置标志,则无需同步并且可以并行执行线程。
谢谢!
如何检查线程 ExecutorService 池中是否正在运行线程?
背景:
如果设置了标志,我想在线程池中的线程之间进行同步。因此,如果该标志设置为 true 以进行同步,那么我必须检查其他线程是否正在运行或等待其完成,然后使用 synchronize 调用阻塞线程,以便其他线程等待这个阻塞线程完成。
如果未设置标志,则无需同步并且可以并行执行线程。
谢谢!
您需要使用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);
}
简而言之,你没有。执行程序不应该以这种方式使用。如果您想手动管理线程,请在没有 Executors 的情况下进行。如果您使用 Executors,请将您的想法从Thread
s 转移到Runnable
s。使用同步或java.util.concurrent
.
如何检查线程 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.
}