2016-04-27 57 views
0

java doc表示在執行寫入操作時,會發生以前未完成的操作。如何解決java7 nio套接字WritePendingException?

當試圖寫一個 異步socket通道和先前的寫拋出未經檢查的異常還沒有完成。

一個簡單的代碼來描述這個階段:

sendMsg(data: ByteBuffer): Future[Unit] = { 
    val p = Promise[Unit] 
    this.synchronized { 
     //socketChannel: AsynchronousSocketChannel is connected socket 
     socketChannel.write(data, 1, new CompletionHandler[Integer, Int] { 
     override def completed(result: Integer, attachment: Int): Unit = { 
      p.trySuccess(Unit) 
     } 

     override def failed(exc: Throwable, attachment: Int): Unit = { 
      p.tryFailure(exc) 
     } 
     } 
    } 
    p.future 
    } 

我試圖鎖定write操作,直到其與此unwork代碼完成:

val writeLock = new ReentrantLock 

def sendMsg(data: ByteBuffer) = { 
    val p = Promise[Unit] 

    writeLock.lock() 

    socketChannel.write(data, 1, new CompletionHandler[Integer, Int] { 
    override def completed(result: Integer, attachment: Int): Unit = { 
     writeLock.unlock() 

     p.trySuccess(Unit) 
    } 

    override def failed(exc: Throwable, attachment: Int): Unit = { 
     p.tryFailure(exc) 
     writeLock.unlock() 
    } 
    }) 
    p.future 
} 

但它拋出IllegalMonitorStateException例外。
希望一些幫助來同時運行它。 此外,我還有一個問題,爲什麼不是java sdk處理它。似乎我應該等待異步操作complete.Thanks

回答

0

是不是Java應該處理這個問題,因爲如果你會失去對你的控制權碼。

您不必「等待」。你寫你的數據,並「寫作」使客戶端無效。當寫入完成(這就是爲什麼你有這種方法),你重新驗證客戶端的寫作。

關鍵概念是,在選擇要寫入的通道時,可以跳過那些在該通道上「無效」的通道。

我幾年前做了一個NIO的異步IO實現,您不妨來看看,以獲得進一步的提示

https://github.com/NadirRoGue/asyncnetworkengine/tree/master/src/org/mmocore/network

採取在 MMOClient.sendPacket() WriteHandler.completed()

+0

看看特別是在'MMOConnection.startWriteTask '在線程池中使用'write'方法的地方。但在'MMOConnection.executeWriteTask'處調用的只鎖定當前線程的方法圍繞'startWriteTask'方法。如何確保'write'處於掛起狀態時'executeWriteTask'不能執行? – LoranceChen

+0

@LoranceChen這就是爲什麼我有'_pendingWrite'標誌,以避免掛起時執行它。另一種方法是使用'completed'方法觸發下一次寫入,而'sendQueue'則有數據包。一旦這個是空的,寫任務將停止被觸發,所以你將不得不使用'sendPacket'(帶有另一個標誌,它最後是相同的)來觸發寫任務 – Nadir

+0

,你能舉個例子嗎?使用lib?我認爲'_pendingWrite'完全沒有影響,因爲'_core.executeWriteTask'會立即返回。 – LoranceChen

相關問題