- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的问题与 this one here 密切相关.正如在那里发布的那样,我希望主线程等到工作队列为空并且所有任务都已完成。然而,我的情况的问题是,每个任务都可能递归地导致提交新任务进行处理。这使得收集所有这些任务的 future 有点尴尬。
我们当前的解决方案使用忙等待循环来等待终止:
do { //Wait until we are done the processing
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} while (!executor.getQueue().isEmpty()
|| numTasks.longValue() > executor.getCompletedTaskCount());
numTasks 是一个随着每个新任务的创建而增加的值。这行得通,但由于等待繁忙,我认为这不是很好。我在想有没有什么好的方法可以让主线程同步等待,直到被显式唤醒。
最佳答案
非常感谢您的所有建议!
最后我选择了我认为相当简单的东西。我发现 CountDownLatch几乎是我需要的。它会阻塞,直到计数器达到 0。唯一的问题是它只能倒计时,不能倒计时,因此在我的动态设置中不起作用,任务可以提交新任务。因此,我实现了一个新类 CountLatch
,它提供了额外的功能。 (见下文)我然后按如下方式使用这个类。
主线程调用 latch.awaitZero()
,阻塞直到 latch 达到 0。
任何线程,在调用 executor.execute(..)
之前调用 latch.increment()
。
任何任务,在即将完成之前,都会调用 latch.decrement()
。
当最后一个任务终止时,计数器将达到 0,从而释放主线程。
欢迎提出进一步的建议和反馈!
public class CountLatch {
@SuppressWarnings("serial")
private static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected int acquireNonBlocking(int acquires) {
// increment count
for (;;) {
int c = getState();
int nextc = c + 1;
if (compareAndSetState(c, nextc))
return 1;
}
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c - 1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
private final Sync sync;
public CountLatch(int count) {
this.sync = new Sync(count);
}
public void awaitZero() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean awaitZero(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void increment() {
sync.acquireNonBlocking(1);
}
public void decrement() {
sync.releaseShared(1);
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}
请注意,increment()
/decrement()
调用可以按照建议封装到自定义的 Executor
子类中,例如,由 Sami Korhonen 编写,或者按照 impl 的建议使用 beforeExecute
和 afterExecute
。看这里:
public class CountingThreadPoolExecutor extends ThreadPoolExecutor {
protected final CountLatch numRunningTasks = new CountLatch(0);
public CountingThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public void execute(Runnable command) {
numRunningTasks.increment();
super.execute(command);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
numRunningTasks.decrement();
super.afterExecute(r, t);
}
/**
* Awaits the completion of all spawned tasks.
*/
public void awaitCompletion() throws InterruptedException {
numRunningTasks.awaitZero();
}
/**
* Awaits the completion of all spawned tasks.
*/
public void awaitCompletion(long timeout, TimeUnit unit) throws InterruptedException {
numRunningTasks.awaitZero(timeout, unit);
}
}
关于java - 执行者 : How to synchronously wait until all tasks have finished if tasks are created recursively?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14535770/
在 java 中不使用“同步”关键字的情况下,是否有其他方法可以同步类或方法? 谢谢, 马利卡琼·科卡塔努尔 最佳答案 您可能想查看并发包中引入的对 JDK 5 的更改。 http://java.su
第 1 部分: 假设下面这段代码 void method1(){ synchronized (lockObject){ method2(); System.ou
我有一个 REST 服务器和一个在移动设备上运行的客户端应用程序。客户端有一些数据并希望从服务器获取数据更新。如何以 RESTful 方式在单个事务中执行此操作? 假设客户有以下元素: widge
我有一个多线程 Java 应用程序。在一种方法中,需要同步一个 ArrayList。由于 arrayList 不是线程安全的,所以我必须使用同步。问题是 ArrayList 类型的对象不是对象的成员变
我正在阅读 Android 示例中的 BluetoothChatService.java 文件,有一件事特别让我感到困惑。 方法在多个位置访问静态成员,并且定义为同步。 在另一部分中,正在访问同一个静
我知道为了实现线程安全和同步,我们使用同步块(synchronized block)或方法。 但我无法理解声明- “Java 中的同步块(synchronized block)在某些对象上同步 ” 任
在 Scala 中使用 JDBC 的示例中,有以下代码: this.synchronized { if (!driverLoaded) loadDriver() } 为什么this.synchro
abstract class A { protected abstract int isRunning(); public void concreteMethod() { synchr
有谁可以分享一下他们的经验吗?“我们什么时候在同步方法和同步块(synchronized block)之间进行调用”有任何性能问题吗? 最佳答案 When do we make a call to u
这是我之前问题的后续问题,Is this variable being safely accessed by using synchronization? 对于下面的程序, Class SubClas
我目前正在为 N 体问题实现多线程版本的 Barnes-Hut 算法。虽然该算法有效,但它不是很优化,我正在尝试减少我的程序的运行时间。 我已经确保有多个线程可以准确地找到我正在使用的空间的边界,并意
我有这门课: public class MyClass { public MyClass(){} public void actionA(){ synchronized
又是一个关于ArrayList和synchronize的问题。 我只想知道这段代码到底做了什么: ArrayList list = ....; synchronized (list) { if
我可以在另一个同步块(synchronized block)中包含同步块(synchronized block)以同步另一个对象吗? 例子: synchronized(myObjetc1){
public class ObjectCounter { private static long numOfInstances = 0; public ObjectCounter(){
我在某处读到,对于 various reasons 应该避免 synchronized(this) .然而,我遇到的一些值得尊敬的代码在构造函数中使用了以下内容: public SomeClass(C
Java 为同步代码的关键部分提供了一种非常方便的习惯用法: synchronized(someObject) { // do something really important all b
我有一个 WeakReference 的 Collections.synchronizedList,_components; 我写了类似下面的内容,希望编译者会提示: public boolean a
使用下面两个版本的Singleton Classes有什么区别 首先我使用的是synchronized(Singleton.class) 在第二个我使用同步(Obj)//第一种类型 公共(public
我正在查看 DatagramSocket 的源代码,我发现了这个: public void disconnect() { synchronized (this) { if (i
我是一名优秀的程序员,十分优秀!