义同上。
而Buffer中大多数的方法都是去改变这3个参数来达到某些功能的:
public final Buffer rewind()
将position置零,并清除标志位(mark)
public final Buffer clear()
将position置零,同时将limit设置为capacity的大小,并清除了标志mark
public final Buffer flip()
先将limit设置到position所在位置,然后将position置零,并清除标志位mark,通常在读写转换时使用
文件映射到内存
public static void main(String[] args) throws Exception {
RandomAccessFile raf = new RandomAccessFile("C:\\mapfile.txt", "rw");
FileChannel fc = raf.getChannel();
// 将文件映射到内存中
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0,
raf.length());
while (mbb.hasRemaining()) {
System.out.print((char) mbb.get());
}
mbb.put(0, (byte) 98); // 修改文件
raf.close();
}
对MappedByteBuffer的修改就相当于修改文件本身,这样操作的速度是很快的。
3. Channel
多线程网络服务器的一般结构:
简单的多线程服务器:
public static void main(String[] args) throws Exception {
ServerSocket echoServer = null;
Socket clientSocket = null;
try {
echoServer = new ServerSocket(8000);
} catch (IOException e) {
System.out.println(e);
}
while (true) {
try {
clientSocket = echoServer.accept();
System.out.println(clientSocket.getRemoteSocketAddress()
+ " connect!");
tp.execute(new HandleMsg(clientSocket));
} catch (IOException e) {
System.out.println(e);
}
}
}
功能就是服务器端读到什么数据,就向客户端回写什么数据。
这里的tp是一个线程池,HandleMsg是处理消息的类。
static class HandleMsg implements Runnable{
省略部分信息
public void run(){
try {
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintWriter(clientSocket.getOutputStream(), true);
// 从InputStream当中读取客户端所发送的数据
String inputLine = null;
long b=System. currentTimeMillis ();
while ((inputLine = is.readLine()) != null)
{
os.println(inputLine);
}
long e=System. currentTimeMillis ();
System. out.println ("spend:"+(e - b)+" ms ");
} catch (IOException e) {
e.printStackTrace();
}finally
{
关闭资源
}
}
}
客户端:
public static void main(String[] args) throws Exception {
Socket client = null;
PrintWriter writer = null;
BufferedReader reader = null;
try {
client = new Socket();
client.connect(new InetSocketAddress("localhost", 8000));
writer = new PrintWriter(client.getOutputStream(), true);
writer.println("Hello!");
writer.flush();
reader = new BufferedReader(new InputStreamReader(
client.getInputStream()));
System.out.println("from server: " + reader.readLine());
} catch (Exception e) {
} finally {
// 省略资源关闭
}
}
以上的网络编程是很基本的,使用这种方式,会有一些问题:
为每一个客户端使用一个线程,如果客户端出现延时等异常,线程可能会被占用很长时间。因为数据的准备和读取都在这个线程中。此时,如果客户端数量众多,可能会消耗大量的系统资源。
解决方案:
使用非阻塞的NIO (读取数据不等待,数据准备好了再工作)
为了体现NIO使用的高效。
这里先模拟一个低效的客户端来模拟因网络而延时的情况:
private static ExecutorService tp= Executors.newCachedThreadPool();
private static final int sleep_time=1000*1000*1000;
public static class EchoClient implements Runnable{
public void run(){
try {
client = new Socket();
client.connect(new InetSocketAddress("localhost", 8000));
writer = new PrintWriter(client.getOutputStream(), true);
writer.