更新时间:2022-09-16 23:24:16
1. 只有非阻塞Channel才能注册,否则会报IllegalBlockingModeException。
2. sk.interestOps(sk.interestOps()& ~SelectionKey.OP_READ);
//处理业务
sk.interestOps(sk.interestOps()| SelectionKey.OP_READ);
sk.interestOps()操作必须在与register()操作在同一个线程,否则不起作用。这个观点被证明是错的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
package com.guojje.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.Set;
public class NioServer {
public static void main(String[] args) throws IOException,
InterruptedException {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind( new InetSocketAddress( "0.0.0.0" , 8080 ));
// Thread.currentThread().sleep(100000);
ssc.configureBlocking( false );
Selector selector = SelectorProvider.provider().openSelector();
ssc.register(selector, SelectionKey.OP_ACCEPT);
while ( true ) {
int readyChannels = selector.select();
System.out.println( "ready channels count:" + readyChannels);
if (readyChannels > 0 ) {
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectedKeys.iterator();
while (it.hasNext()){
SelectionKey sk = it.next();
it.remove();
if ((sk.readyOps() & SelectionKey.OP_ACCEPT) != 0 ){
ServerSocketChannel serverChannel = (ServerSocketChannel)sk.channel();
SocketChannel sc = serverChannel.accept();
System.out.println(sc);
sc.configureBlocking( false );
sc.register(selector, SelectionKey.OP_READ);
}
if ((sk.readyOps() & SelectionKey.OP_READ) != 0 ){
ReadableByteChannel rc = (ReadableByteChannel)sk.channel();
sk.interestOps(sk.interestOps() & ~SelectionKey.OP_READ);
ByteBuffer bb = ByteBuffer.allocate( 50 );
rc.read(bb);
System.out.println( new String(bb.array(), 0 ,bb.position()));
//sk.interestOps(sk.interestOps() | SelectionKey.OP_READ);
Thread anoThread = new Thread( new AnotherThread(sk));
anoThread.start();
anoThread.join();
}
}
}
}
}
} package com.guojje.nio;
import java.nio.channels.SelectionKey;
public class AnotherThread implements Runnable {
private SelectionKey sk;
public AnotherThread(SelectionKey sk){
this .sk = sk;
}
@Override
public void run() {
sk.interestOps(sk.interestOps() | SelectionKey.OP_READ);
}
} |
三、 一个数组byte[] bs = new byte[10],bs[0]=10, bs[1]=9, bs[2]=8
如果想把SocketChannel读入剩余7个元素,而不影响其他,可以这样:
ByteBuffer bb = ByteBuffer.wrap(bs,3,7).slice();
如果仅仅用ByteBuffer.wrap(bs,3,7),则bb的capacity仍为bs.length.
而用slice之后,bb的capacity为7,所以你对bb的任务操作都不会影响到前三个元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.guojje.nio;
import java.nio.ByteBuffer;
public class TestSlice {
public static void main(String[] args) {
byte [] bs = new byte [ 10 ];
bs[ 0 ]= 10 ;
bs[ 1 ]= 9 ;
bs[ 2 ]= 8 ;
ByteBuffer bb1 = ByteBuffer.wrap(bs, 3 , 7 );
ByteBuffer bb2 = ByteBuffer.wrap(bs, 3 , 7 ).slice();
System.out.println(bb1.capacity());
System.out.println(bb2.capacity());
} } |
四、 ByteBuffer.put ()与 ByteBuffer.get()都会增长position,并且上限都是limit.
因为:
1
2
3
4
5
|
final int nextGetIndex() { // package-private
if (position >= limit)
throw new BufferUnderflowException();
return position++;
}
|
1
2
3
4
5
|
final int nextPutIndex() { // package-private
if (position >= limit)
throw new BufferOverflowException();
return position++;
}
|
position都会增长。
五、 一个 channal 对应同一个SelectionKey in the same selector
六、channel.register操作may block if invoked concurrently with another registration[another.register(...)]
or selection operation[selector.select(...)] involving in the same selector.
这是因为register操作需要regLock与keyLock锁。
七. selectionKey.cancel():
The key will be removed from all of the selector's key sets during the next selection operation[select(...)] 。
cancel may block briefly if invoked concurrently with a cancellation[cancel()] or selection operation[select(...)]
involving the same selector.
参考:http://www.blogjava.net/adapterofcoms/archive/2010/03/02/314242.html
本文转自 anranran 51CTO博客,原文链接:http://blog.51cto.com/guojuanjun/642680