ThreadPoolExecutor.AbortPolicy:表示拒绝任务并抛出异常
ThreadPoolExecutor.DiscardPolicy:表示拒绝任务但不做任何动作
ThreadPoolExecutor.CallerRunsPolicy:表示拒绝任务,并在调用者的线程中直接执行该任务 ThreadPoolExecutor.DiscardOldestPolicy:表示先丢弃任务队列中的第一个任务,然后把这个任务加进队列。
LinkedBlockingQueue 和 ArrayBlockingQueue,用 LinkedBlockingQueue 的好处在于没有大小限制 假设队列大小为 10,corePoolSize 为 3,maximumPoolSize 为 6,那么当加入 20 个任务时,执行的顺序就是这样的:首先执行任务 1、2、3,然后任务 4~13 被放入队列。这时候队列满了,任务 14、15、16 会被马上执行,而任务 17~20 则会抛出异常。最终顺序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。
状态变量:position limit capacity 这三个变量一起可以跟踪缓冲区的状态和它所包含的数据。 在从通道读取时,将所读取的数据放到底层的数组中。position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。因此,如果从通道中读三个字节到缓冲区中,那么缓冲区的 position 将会设置为3,指向数组中第四个元素。 在写入通道时,您是从缓冲区中获取数据。 position 值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的 position 将被设置为5,指向数组的第六个元素。 limit 变量表明还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。position 总是小于或者等于 limit。 缓冲区的 capacity 表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小,或者至少是指定了准许我们使用的底层数组的容量。limit 决不能大于 capacity。
flip() 方法做两件非常重要的事:
1. 它将 limit 设置为当前 position。
2. 它将 position 设置为 0。
clear() 方法重设缓冲区以便接收更多的字节。 Clear 做两种非常重要的事情:
1. 它将 limit 设置为与 capacity 相同。
2. 它设置 position 为 0。
buffer.position(3);
buffer.limit(7);
ByteBuffer slice = buffer.slice();
片 是缓冲区的 子缓冲区 。不过,片段 和 缓冲区 共享同一个底层数据数组。
for (int i = 0; i < slice.capacity(); i++) {
byte b = slice.get(i);
b *= 11;
slice.put(i, b);
}
原缓冲区中的内容:
buffer.position( 0 );
buffer.limit(buffer.capacity());
while (buffer.hasRemaining()) {
System.out.println(buffer.get());
}
//0 1 2 33 44 55 66 7 8 9
asReadOnlyBuffer() 只读缓冲区
ScatteringByteChannel 和 GatheringByteChannel 分散/聚集 I/O
long read(ByteBuffer[] dsts)
long read(ByteBuffer[] dsts, int offset, int length)
long write(ByteBuffer[] srcs)
long write(ByteBuffer[] srcs, int offset, int length)
因为每一个缓冲区都跟踪自己还可以接受多少数据,所以分散读取会自动找到有空间接受数据的第一个缓冲区。在这个缓冲区填满后,它就会移动到下一个缓冲区。 分散/聚集 I/O 对于将数据划分为几个部分很有用。例如,您可能在编写一个使用消息对象的网络应用程序,每一个消息被划分为固定长度的头部和固定长度的正文。您可以创建一个刚好可以容纳头部的缓冲区和另一个刚好可以容难正文的缓冲区。当您将它们放入一个数组中并使用分散读取来向它们读入消息时,头部和正文将整齐地划分到这两个缓冲区中。
if(key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
} else if (key.isReadable()) {
SocketChannel sc = (SocketChannel)key.channel();
// Read the data
}
Selector selector = Selector.open();
int num = selector.select(); //调用 Selector 的 select() 方法。这个方法会阻塞,直到至少有一个已注册的事件发生
Set selectedKeys = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey)it.next();
// ... deal with I/O event ...
}
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking( false );
SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
//ServerSocketChannel 的唯一事件类型
ServerSocket ss = ssc.socket();
InetSocketAddress address = new InetSocketAddress(ports[i]);
ss.bind( address );
SelectionKey newKey = sc.register(selector, SelectionKey.OP_READ); //SocketChannel