2008-10-06 10 views
6

मैंने और ObjectOutputStream को अवरुद्ध SocketChannel पर बनाया और समवर्ती रूप से पढ़ने और लिखने की कोशिश कर रहा हूं। (ब्लॉक वस्तु SelectableChannel#blockingLock() द्वारा दिया पर) लाइन (ए) में ब्लॉकजावा: ऑब्जेक्ट (इन | आउट) putStreams के माध्यम से एक अवरुद्ध सॉकेट चैनल पर समवर्ती पढ़ता है और लिखता है?

socketChannel = SocketChannel.open(destNode); 
objectOutputStream = new ObjectOutputStream(Channels.newOutputStream(socketChannel)); 
objectInputStream = new ObjectInputStream(Channels.newInputStream(socketChannel)); 

Thread replyThread = new Thread("SendRunnable-ReplyThread") { 
    @Override 
    public void run() { 
     try { 
      byte reply = objectInputStream.readByte();//(A) 
      //..process reply 
     } catch (Throwable e) { 
      logger.warn("Problem reading receive reply.", e); 
     } 
    } 
}; 
replyThread.start(); 

objectOutputStream.writeObject(someObject);//(B) 
//..more writing 

समस्या लाइन (बी) पर लिखने है पढ़ने जब तक पूरे करता है: मेरे कोड कुछ इस तरह है। लेकिन ऐप तर्क यह निर्देश देता है कि जब तक सभी लिखने को पूरा नहीं किया जाता है, तो हमारे पास एक प्रभावी डेडलॉक होता है।

SocketChannel javadocs का कहना है कि समवर्ती पढ़ने और लिखने का समर्थन किया जाता है।

मैं ऐसी कोई समस्या का सामना करना है जब मैं एक नियमित रूप से सॉकेट समाधान की कोशिश की:

Socket socket = new Socket(); 
socket.connect(destNode); 
final OutputStream outputStream = socket.getOutputStream(); 
objectOutputStream = new ObjectOutputStream(outputStream); 
objectInputStream = new ObjectInputStream(socket.getInputStream()); 

हालांकि, तो मैं नहीं लाभ FileChannel#transferTo(...)

उत्तर

1

के प्रदर्शन लाभ के लिए ले आप समवर्ती InputStream और OutputStream उपयोग करना चाहते हैं कर सकते हैं सोकेट चैनेल के साथ, स्रोत को देखने से, ऐसा प्रतीत होता है कि आपको सॉकेटChannel.socket() को कॉल करने की आवश्यकता है और उन धाराओं का उपयोग करें जो थोड़ा अलग तरीके से व्यवहार करते हैं।

+0

मैंने इसे सॉकेटChannel.socket() का उपयोग करने के लिए बदलने की कोशिश की। (आउट | इन) putStream प्राप्त करें, लेकिन इससे कोई फर्क नहीं पड़ता। आउटपुटस्ट्रीम पहले जैसा ही प्रतीत होता है: अज्ञात आंतरिक वर्ग चैनल # newOutputStream (आउटपुटस्ट्रीम) द्वारा लौटाया जाता है। –

+0

यह इनपुटस्ट्रीम है जो उप-वर्ग (परीक्षण नहीं किया गया) में बदलना चाहिए। –

+4

* चेक बगस्टर * http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=d76c6fabad9827be488fceb8d9f4?bug_id=4509080 बहुत सारी बग, कम प्राथमिकता। ऐसा लगता है कि आपको पुराने स्कूल java.net सॉकेट से शुरू करने के लिए मजबूर होना पड़ता है। –

2

यह java.nio.channels.Channels में एक बग प्रतीत होता है (टॉम हौटिन के लिए धन्यवाद; अगली बार इसे उत्तर के रूप में पोस्ट करें)। एक अच्छा वर्णन और कार्यवाही वर्णित है here (वास्तव में बग टॉम सूचीबद्ध एक डुप्लिकेट):

मैंने वर्कअराउंड का परीक्षण किया और यह काम करता है।

0

दिलचस्प बग! आप कहते हैं कि आप FileChannel # स्थानांतरण का उपयोग नहीं कर सकते हैं। FileChannel # स्थानांतरण में जाने से पहले चैनल से # newChannel का उपयोग कर चैनलों में गैर-एनआईओ सॉकेट के I/O धाराओं को लपेटने के बारे में कैसे?

+0

मुझे लगता है कि 'हस्तांतरण के लिए केवल प्रदर्शन लाभ हैं यदि' WritableByteChannel' एक वास्तविक एनआईओ कक्षा है जिसके लिए इसका विशिष्ट समर्थन है, नियमित आईओ कक्षा का एक रैपर नहीं। यकीन नहीं, थो। –

+0

इसके बारे में सोचने के लिए आओ, मुझे आश्चर्य है कि किसी अन्य उत्तर में वर्णित कार्यवाही के अनुसार एक डमी बाइट चैनेल में सॉकेट चैनल को लपेटने से हस्तांतरण को रोक दिया जाएगा। –

2

बग रिपोर्ट में कामकाज मेरे लिए काम करता है। यह ध्यान देने योग्य है कि इनपुट या आउटपुट के लिए केवल एक काम करने के लिए कामकाज के लिए लपेटा जाना आवश्यक है - इसलिए यदि प्रदर्शन एक दिशा में विशेष रूप से महत्वपूर्ण है तो आप कम महत्वपूर्ण को लपेट सकते हैं और सुनिश्चित कर सकते हैं कि अन्य सभी अनुकूलन प्राप्त करेंगे इसके लिए उपलब्ध है।

public InputStream getInputStream() throws IOException { 
    return Channels.newInputStream(new ReadableByteChannel() { 
     public int read(ByteBuffer dst) throws IOException { 
      return socketChannel.read(dst); 
     } 
     public void close() throws IOException { 
      socketChannel.close(); 
     } 
     public boolean isOpen() { 
      return socketChannel.isOpen(); 
     } 
    }); 
} 

public OutputStream getOutputStream() throws IOException { 
    return Channels.newOutputStream(socketChannel); 
}