如何检查线程ExecutorService中的线程是否正在运行?
背景:
如果设置了标志,我想在线程池中的线程之间进行同步。
因此,如果将标志设置为true以进行同步,那么我必须检查其他线程是否正在运行或等待其完成,然后使用synchronize调用阻塞线程,以便其他线程等待此阻塞线程完成。
如果未设置flag,则无需同步,并且可以并行执行线程。
谢谢!
答案 0 :(得分:6)
您需要使用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()
- 但我认为你知道这个并且出于某种原因不能。
修改强>
稍微探视一下,看看这是否可以整理,我遇到了this。这提示了一个更简洁的解决方案:
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);
}
答案 1 :(得分:4)
如何检查线程ExecutorService中的线程是否正在运行?
如果您只是想知道某个帖子是否在特定的ExecutorService
中运行,您可以创建具有特定ExecutorService
的{{1}}并让它为该主题添加一些特殊属性,比如一个特殊的名字。
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);
答案 2 :(得分:3)
简而言之,你没有。执行者不应该以这种方式使用。如果要手动管理线程,请在没有Executors的情况下执行。如果您使用执行者,请将您的思维从Thread
改为Runnable
。使用同步或java.util.concurrent
中的任何高级抽象,使您的Runnables或类和方法成为线程安全的。
答案 3 :(得分:3)
如何检查线程ExecutorService中的线程是否正在运行?
这在ExecutorService
线程池的上下文中没有意义。该池正在执行您的Runnable
(或Callable
)类。也许您应该问的是,如果您可以查看特定作业是否在池中运行。
如果要完成此操作,那么run()
(或call()
)方法前面的每个作业都可以检查某种synchronized
对象并等待或继续必要。也可能是您可以拥有多个线程池并将您的作业分成更小的部分,这样您就可以控制作业的哪些部分同时运行。
然而,正如@Ralf指出的那样,你正在做的是反对线程池的整个点。线程池的重点是作业以异步方式运行。如果你需要很多同步点,那么你可能需要重新设计。
如果您提供有关您的环境的更多详细信息,我们可以更具体地解决您的基本问题。