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);