簡體   English   中英

Java的ReadableByteChannelImpl行為不一致

[英]Java's ReadableByteChannelImpl inconsistent behaviour

當我使用Channels.newChannel(is)從InputStream創建一個通道時,Java標准庫返回一個ReadableByteChannelImpl,它是:

   private static class ReadableByteChannelImpl
       extends AbstractInterruptibleChannel    // Not really interruptible
       implements ReadableByteChannel
   {
       InputStream in;
       private static final int TRANSFER_SIZE = 8192;
       private byte buf[] = new byte[0];
       private boolean open = true;
       private Object readLock = new Object();

       ReadableByteChannelImpl(InputStream in) {
           this.in = in;
       }

       public int read(ByteBuffer dst) throws IOException {
           int len = dst.remaining();
           int totalRead = 0;
           int bytesRead = 0;
           synchronized (readLock) {
               while (totalRead < len) {
                   int bytesToRead = Math.min((len - totalRead),
                                              TRANSFER_SIZE);
                   if (buf.length < bytesToRead)
                       buf = new byte[bytesToRead];
                   if ((totalRead > 0) && !(in.available() > 0))
                       break; // block at most once
                   try {
                       begin();
                       bytesRead = in.read(buf, 0, bytesToRead);
                   } finally {
                       end(bytesRead > 0);
                   }
                   if (bytesRead < 0)
                       break;
                   else
                       totalRead += bytesRead;
                   dst.put(buf, 0, bytesRead);
               }
               if ((bytesRead < 0) && (totalRead == 0))
                   return -1;

               return totalRead;
           }
       }

       protected void implCloseChannel() throws IOException {
           in.close();
           open = false;
       }
   }

如您所見,它在第一次調用read(ByteBuffer dst)時會阻塞,再也不會阻塞。 看到:

           if ((totalRead > 0) && !(in.available() > 0))
               break; // block at most once

這種奇怪行為的背后原因是什么?

另外,在沒有實際使此通道真正可中斷的情況下擴展AbstractInterruptibleChannel的動機是什么?

如果已經讀取了至少一個字節並且基礎流宣布沒有字節可用 ,它將不會阻塞。 請注意,即使某些字節可用, InputStream#available()可以返回零,但它承諾的字節數要多於不阻塞而無法讀取的字節數。 因此,此ReadableByteChannel會努力讀取至少一個字節-假設提供的ByteBuffer具有至少一個字節的空間-並且這樣做之后,將不會嘗試再次讀取基礎流,除非該流承諾更多可用字節無阻塞。

至於為什么ReadableByteChannelImpl擴展AbstractInterruptibleChannel ,我懷疑這是為了確保包裝的InputStream在調用Channel#close()后能夠正確Channel#close() ,該協議的合約由InterruptibleChannel#close()進一步完善。 擴展AbstractInterruptibleChannel允許ReadableByteChannelImpl借用其線程安全的打開-關閉狀態保護。

如您所說,這是一種錯誤的廣告,並不是真正的可中斷性,但是它可以被一個單獨的線程關閉,並且這樣做是冪等的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM