什么Java并发类可能对我有帮助?

时间:2010-03-19 17:22:45

标签: java concurrency

我正在尝试编写一些具有以下行为的代码:

  • 各种线程(线程X)对X进行多次并发和随机调用
  • 在将来的某个时刻,通过一个线程(线程Y)
  • 对Y进行一次调用
  • 在调用Y之前,应该允许X通过未挑战的,并且对X的并发调用完全有效
  • 一旦调用Y,就应该允许对X的任何现有调用完成,但是应该以某种方式拒绝对X的新调用(RuntimeException等)
  • 在完成对X的所有现有调用之前,Y不应继续执行
  • 更新 :当调用Y时,它应该向在线程X中运行的对象发送一个信号,告诉它们以某种优雅的方式中止()(理想情况下很快完成,以便Y可以继续)

我查看了使用Semaphore,CountDownLatch,甚至编写了我自己的AbstractQueuedSynchronizer,但没有一个符合上述要求。例如,CountDownLatch假设您知道要对X进行多少次调用,这是我们不知道的。

似乎我几乎想要一个CountUpDownLatch的混合物,也许是某种简单的AtomicBoolean,但这就是我目前正在使用的东西,我发现自己时不时会陷入僵局。然后,我正在使用一个sketchy looking implementation的CountUpDownLatch,它是HSQLDB的一部分,严重看起来不是线程安全的。

关于如何解决这个问题的任何想法?

4 个答案:

答案 0 :(得分:3)

看起来像ReentrantReadWriteLock的任务。像这样:

class A {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public void x() {
        if (!lock.readLock().tryLock()) throw new RuntimeException();
        try {
            ...
        } finally {
            lock.readLock().unlock();
        }
    }

    public void y() {
        lock.writeLock().lock();
        try {
            ...
        } finally {
            lock.writeLock().unlock();
        }
    }
}

答案 1 :(得分:2)

Java 7正在推出一个新的并发构造类java.util.concurrent.Phaser。移相器是一个美化的圆柱形屏障,允许等待并发执行的特定阶段(或迭代)。您可以在JSR 166's Interest Site下载最新的二进制jar。

我的想法是你有一个不稳定的boolean yHasEnetered标志,它将默认值初始化为false。所以在你的X执行中你可以这样做:

        if(yHasEnetered)
            throw new IllegalStateException();
        phaser.register();
        //do work here
        phasre.arrive();

移相器本身将保持所有注册方的运行计数,以便当Y线程进入时,它可以相应地设置标志,注册自己并等待提前。

        yHasEntered=true;
        int phase = phaser.register();
        phaser.arriveAndAwaitAdvance(phase);
        //do y work here
        yHasEntered=false;

此时为Y线程。它将自己注册到相位器当前所处的阶段,到达并等待执行的所有其他线程到达它们各自的到达块。

答案 2 :(得分:0)

考虑使用ExecutorService的实现。使用submit()方法添加任务,然后告诉服务不要使用shutdown()方法接受更多任务 - 已经接受的任务将正常完成。

答案 3 :(得分:0)

好的,如何使用ActiveObject

class X {
    private static final ExecutorService service = Executors.newCachedThreadPool();


    public void x(){
       //Using anonymous class for brevity. Normal Runnable is ok. May be static inner class.  
       service.submit(new Runnable(){
                             @Override
                             public void run(){
                                   //do stuff
                             }
                       });
    }

    //Derived from Java6 ExecutorService API        
    public void shutDownAndAwait(){
        service.shutdownNow();
        try{
           if (!service.awaitTermination(60, TimeUnit.SECONDS))
              throw new TerminationException("Service did not terminate");
           }
        } catch (InterruptedException ie) {
           // (Re-)Cancel if current thread also interrupted
           service.shutdownNow();
           // Preserve interrupt status
           Thread.currentThread().interrupt();
        }
   }//shutdownAndAwait

}//X


class Y {

    private final X x = //inject reference

    public void y(){
        x.shutdownAndAwait();
    }
}

问题是现在执行x()是异步的,因此调用x()的原始线程在完成时不确定。当y()被调用时,它们不会被打断......