Java 移相器问题(使用JSR166y和最新版本6的JDK)

Java 移相器问题(使用JSR166y和最新版本6的JDK),java,multithreading,concurrency,race-condition,phaser,Java,Multithreading,Concurrency,Race Condition,Phaser,所以,我有一个相位器,它非常灵活,但我似乎遗漏了一些东西我已经成功地使用了CyclicBarrier,但现在我还想要一些更灵活的东西,正如我所说的。下面是代码: 声明: 代码: 试试看{ INFO(“已连接的-对等ID属性:”+SYS\u NEWLINE+peerSocket+SYS\u NEWLINE+pID,true); final int peerkquerys=sp.getInteger(peerSocket); peerObjects=新字符串[peerKQueries]; peerV

所以,我有一个相位器,它非常灵活,但我似乎遗漏了一些东西
我已经成功地使用了CyclicBarrier,但现在我还想要一些更灵活的东西,正如我所说的。下面是代码:

声明:


代码:

试试看{
INFO(“已连接的-对等ID属性:”+SYS\u NEWLINE+peerSocket+SYS\u NEWLINE+pID,true);
final int peerkquerys=sp.getInteger(peerSocket);
peerObjects=新字符串[peerKQueries];
peerValues=新的BigDecimal[peerKQueries];
for(int i=0;i到达HT阶段1a。总到达量:“+htPhaser1a.getArrivedParties(),true);
logger.INFO(“超级对等线程”+线程ID+“将前进到HT阶段1b/2(阶段编号为“+阶段1A+”),为真);
//最后一个对等方也应该解除障碍。
if(htPhaser1a.getArrivedParties()==TOTAL_PEERS.get()){
htPhaser1a.arrival();
同步器。倒计时();
}
htPhaser1a.提前中断等待(相位1A,30,时间单位为秒);
}
}捕获(IOE异常){
错误(“超级对等线程”+线程ID+“遇到I/O错误”,true);
sp.close(peerSocket);
抛出新的IllegalThreadStateException();
}捕获(超时异常e){
logger.INFO(“超级对等线程”+线程ID+”超时,但将进入HT阶段1b/2“,为真);
if(是否已超时。比较数据集(false,true)){
INFO(“超时时未到达的参与方:”+(htPhaser1a.getUnarrivedParties()-1),true);
重置关键数据(htPhaser1a.getArrivedParties());
htPhaser1a.强制终止();
实例化ehtphase1b();
实例化ehtphase2();
实例化ehtpatch();
同步器。倒计时();
}
}最后{
INFO(“超级对等线程”+线程ID+“被阻止!”,true);
同步器。等待();
INFO(“超级对等线程的”+线程ID+“阻止放弃!”,true);
}
sp.getSomething()是I/O调用。
考虑到此代码示例由多个线程运行。

这是我的问题:我已经确保不会有超过MAX_的客户到达phaser,所以如果MAX_的客户到达,一切都很好。但是,我遇到了TimeoutException的问题。第一个是一个时间窗口(也称为竞争条件),客户机(称为线程a)将能够到达该阶段,然后线程B中发生TimeoutException,我正在线程B中动态实例化另一个具有到达方数(称为5)的阶段器,但线程a已经到达该阶段(称为阶段1A未发现<0)。我该怎么纠正呢?我曾考虑使用信号灯,但我认为这不值得付出努力,因为这样我可能需要重新思考我的做法。我还考虑过使用一个计时器,增加一个
AtomicInteger
变量,并在计时器过期时动态实例化移相器。你对如何解决这个问题有什么想法吗?

编辑:
文档有一个
bulkRegister(int parties)
方法,但它的措词有点奇怪:

将给定数量的新未更正的参与方添加到此移相器。如果正在进行的onAdvance(int,int)调用正在进行中,此方法可能会在返回之前等待其完成。如果该移相器有一个父级,且给定的参与方数量大于零,且该移相器以前没有注册参与方,则该子移相器也将在其父级注册。如果此相器终止,则尝试注册无效,并返回负值。

问题:“可能”这个词让我困惑!“可能”是指“可能”还是“可能”是指“遗嘱”?

编辑:
已解决。检查下面我的答案。

声明:


代码:

。。。
htPeerPhaser.register();//只打过一次电话。
...
//注意:服务器应用程序已保证到达的对等方数量不超过最大数量。
试一试{
INFO(“已连接的-对等ID属性:”+SYS\u NEWLINE+peerSocket+SYS\u NEWLINE+pID,true);
final int peerkquerys=sp.getInteger(peerSocket);
peerObjects=新字符串[peerKQueries];
peerValues=新的BigDecimal[peerKQueries];
for(int i=0;i为HT第1阶段注册”,为真);
logger.INFO(“超级对等线程”+线程ID+“将前进到HT阶段1/2”,true);
//最后一个对等方也应该解除障碍。
if(htPeerPhaser.getRegisteredParties()==TOTAL_PEERS.get()+1){
htPeerPhaser.forceTermination();
PEER.countDown();
}
htPeerPhaser.WaitingAdvanceInterruptive(注册ID,30,时间单位:秒);
}捕获(IOE异常){
错误(“超级对等线程”+线程ID+“遇到I/O错误”,true);
sp.close(peerSocket);
抛出新的IllegalThreadStateException();
}捕获(超时异常e){
htPeerPhaser.forceTermination();
logger.INFO(“超级对等线程”+线程ID
private static final CountDownLatch synchronizer = new CountDownLatch(1);
private static AtomicBoolean HAS_TIMED_OUT = new AtomicBoolean(false);
try {
    logger.INFO("CONNECTED - Peer ID properties: " + SYS_NEWLINE + peerSocket + SYS_NEWLINE + pID, true);

    final int peerKQueries = sp.getInteger(peerSocket);
    peerObjects = new String[peerKQueries];
    peerValues = new BigDecimal[peerKQueries];
    for ( int i = 0; i < peerObjects.length; i++ )
       peerObjects[i] = sp.getString(peerSocket);
    for ( int i = 0; i < peerValues.length; i++ )
       peerValues[i] = sp.getBigDecimal(peerSocket);

    final int phase1a = htPhaser1a.arrive();
    if ( phase1a < 0 ) {
        logger.ERROR("Rejecting Super Peer thread " + THREAD_ID + " because it arrived lately for Phase 1a!", true);
        sp.close(peerSocket);
        throw new IllegalThreadStateException();
    } else {
        logger.INFO(pID + " -> Arrived in HT phase 1a. Total arrivals: "+htPhaser1a.getArrivedParties(), true);
        logger.INFO("Super Peer thread " + THREAD_ID + " will advance to HT Phase 1b/2 (phase number is "+phase1a+").", true);
        // The last peer should also unblock the barrier.
        if ( htPhaser1a.getArrivedParties() == TOTAL_PEERS.get() ) {
          htPhaser1a.arrive();
          synchronizer.countDown();
        }
            htPhaser1a.awaitAdvanceInterruptibly(phase1a, 30, TimeUnit.SECONDS);
    }

} catch (IOException e) {
    logger.ERROR("Super Peer thread " + THREAD_ID + " encountered an I/O error.", true);
    sp.close(peerSocket);
    throw new IllegalThreadStateException();
} catch (TimeoutException e) {
    logger.INFO("Super Peer thread " + THREAD_ID + " timed out but will advance to HT Phase 1b/2.", true);
    if ( HAS_TIMED_OUT.compareAndSet(false, true) ) {
        logger.INFO("Parties NOT arrived in the timeout: "+(htPhaser1a.getUnarrivedParties()-1), true);
        resetCriticalData(htPhaser1a.getArrivedParties());
        htPhaser1a.forceTermination();
        instantiateHTPhase1b();
        instantiateHTPhase2();
        instantiateHTPatch();
        synchronizer.countDown();
    }
} finally {
    logger.INFO("Super Peer thread "+THREAD_ID+" is blocked!", true);
    synchronizer.await();
    logger.INFO("Super Peer thread's "+THREAD_ID+" blocking waived!", true);
}
private static final CountDownLatch PEER = new CountDownLatch(1);
private static AtomicBoolean HAS_TIMED_OUT = new AtomicBoolean(false);
htPeerPhaser = new Phaser();
...
htPeerPhaser.register(); // Called only once.
...
// Note: Server application has guaranteed that no more than the maximum number of peers will arrive.
try {
    logger.INFO("CONNECTED - Peer ID properties: " + SYS_NEWLINE + peerSocket + SYS_NEWLINE + pID, true);
    final int peerKQueries = sp.getInteger(peerSocket);
    peerObjects = new String[peerKQueries];
    peerValues = new BigDecimal[peerKQueries];
    for ( int i = 0; i < peerObjects.length; i++ )
        peerObjects[i] = sp.getString(peerSocket);
    for ( int i = 0; i < peerValues.length; i++ )
        peerValues[i] = sp.getBigDecimal(peerSocket);
    final int registrationID = htPeerPhaser.bulkRegister(1);
    if ( registrationID < 0 ) {
        logger.ERROR("Rejecting Super Peer thread " + THREAD_ID + " because peer registration has stopped!", true);
        sp.close(peerSocket);
        throw new IllegalThreadStateException();
    }
    logger.INFO(pID + " -> Registered for HT phase 1.", true);
    logger.INFO("Super Peer thread " + THREAD_ID + " will advance to HT Phase 1/2.", true);
    // The last peer should also unblock the barrier.
    if ( htPeerPhaser.getRegisteredParties() == TOTAL_PEERS.get()+1 ) {
        htPeerPhaser.forceTermination();
        PEER.countDown();
    }
    htPeerPhaser.awaitAdvanceInterruptibly(registrationID, 30, TimeUnit.SECONDS);

} catch (IOException e) {
    logger.ERROR("Super Peer thread " + THREAD_ID + " encountered an I/O error.", true);
    sp.close(peerSocket);
    throw new IllegalThreadStateException();
} catch (TimeoutException e) {
    htPeerPhaser.forceTermination();
    logger.INFO("Super Peer thread " + THREAD_ID + " timed out but will advance to HT Phase 1b/2.", true);
    if ( HAS_TIMED_OUT.compareAndSet(false, true) && htPeerPhaser.getRegisteredParties() < TOTAL_PEERS.get()+1 ) {
        final int arrivedPeers = htPeerPhaser.getRegisteredParties()-1;
        logger.INFO("Parties that arrived before timeout: "+arrivedPeers, true);
        final int unarrivedPeers = TOTAL_PEERS.get()-arrivedPeers;
        logger.INFO("Parties NOT arrived due to timeout: "+unarrivedPeers, true);
        resetCriticalData(arrivedPeers);
        instantiateHTPhase1b();
        instantiateHTPhase2();
        instantiateHTPatch();
        PEER.countDown();
        logger.INFO("Super Peer thread " + THREAD_ID + " re-instantiated critical data.", true);
    }
}
logger.INFO("Super Peer thread "+THREAD_ID+" is blocked!", true);
PEER.await();
logger.INFO("Super Peer thread's "+THREAD_ID+" blocking waived!", true);