NIO与网络编程之AIO的使用

在学习IO技术时,需要了解同步阻塞 同步非阻塞 异步阻塞 异步非阻塞

6.1 AsynchronousFileChannel类的使用

AsynchronousFileChannel类用于读取、写入和操作文件的异步通道。
6.1.1 获取此通道文件的独占锁

public final Future<FileLock> lock()方法的作用是获取此通道文件的独占锁,返回一个Future对象,Future的get()方法在成功完成时返回FileLock.

public class TestMethod_lock {

	public static void main(String[] args) throws IOException {
		Path path = Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
		Future<FileLock> future = channel.lock();
		try {
			FileLock lock = future.get();
			System.out.println("A 获得锁"+System.currentTimeMillis());
			Thread.sleep(8000);
			lock.release();
			System.out.println("A释放锁"+System.currentTimeMillis());
			channel.close();
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		} catch (ExecutionException e) {
			
			e.printStackTrace();
		}
		

	}

}
-------------------------
public class TestMethod_lock2 {

	public static void main(String[] args) throws IOException {
		
		Path path = Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
		Future<FileLock> future = channel.lock();
		try {
			FileLock lock = future.get();
			System.out.println("B 获得锁"+System.currentTimeMillis());
			
			lock.release();
			System.out.println("B释放锁"+System.currentTimeMillis());
			channel.close();
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		} catch (ExecutionException e) {
			
			e.printStackTrace();
		}
		

	}

}

6.1.2 获取通道文件给定区域的锁

public abstract Future <FileLock> lock(long position,long size,boolean shared)方法的作用是获取此通道文件给定区域的锁。
该方法的行为与 lock(long ,long ,boolean Object,CompletionHandler)方法完全相同,不同之处在于,此方法不指定CompletionHandler程序。

在两个进程对同一个文件锁定范围有重叠时,会出现阻塞的状态。

6.1.3 返回此通道当前大小与通道打开状态

public abstract long size()方法的作用是返回此通道文件的当前大小
public boolean isOpen()方法的作用是判断通道是否呈打开的状态

6.1.4 CompletionHandler接口的使用

public final <A> void lock(A attachment,CompletionHandler<FileLock,? super A> handler)方法的作用是获取此通道文件的独占锁。

public class TestMethod_lock3 {

	public static void main(String[] args) throws IOException, InterruptedException {
		Path path =Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
		System.out.println("begin time="+System.currentTimeMillis());
		channel.lock("我是附加值",new CompletionHandler<FileLock,String>(){

			@Override
			public void completed(FileLock result, String attachment) {
				System.out.println("Completed attachment="+attachment);
				try {
					result.release();
					channel.close();
					System.out.println("release and close");
				} catch (IOException e) {
					
					e.printStackTrace();
				}
				
			}

			@Override
			public void failed(Throwable exc, String attachment) {
				System.out.println("failed attachment="+attachment);
				System.out.println("getMessage="+exc.getMessage());
			}
			
		});
		
           System.out.println("end time="+System.currentTimeMillis());
           Thread.sleep(3000);
	}

}

运行结果:
begin time=1559027496370
end time=1559027496372
Completed attachment=我是附加值
release and close

6.1.5 public void failed(Throwable exc,A attachment)方法调用时机

IO操作异常时执行。

6.1.6 执行指定范围的锁定与传入附件及整合接口

public abstract<A> void lock(long position,long size,boolean shared,A attachment,CompletionHandler <Filelock,? super A> handler)

6.1.7 public final <A> void lock(A attachment,CompletionHandler &FileLock, ? super A> handler)方法获得不到锁,一直等待

6.1.8 数据读取方法1

public abstract Future <Integer> read (ByteBuffer dst,long position)方法的作用是从给定的文件位置开始,从该通道将字节序列读入给定的缓冲区。此方法从给定的文件位置开始,将从该通道的字节序列读取到给定的缓冲区。此方法返回Future对象。

public class ReadTest {

	public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
		Path path = Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
		ByteBuffer buffer = ByteBuffer.allocate(3);
		Future<Integer> future = channel.read(buffer, 0);
		System.out.println("length="+future.get());
		channel.close();
		byte[] byteArray = buffer.array();
		for(int i = 0;i<byteArray.length;i++) {
			System.out.println((char)byteArray[i]);
		}

	}

}
运行结果:
length=3
1
2
3

6.1.8 数据读取方法2

public class ReadTest2 {

	public static void main(String[] args) throws IOException {

		Path path = Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
		ByteBuffer buffer = ByteBuffer.allocate(3);
		channel.read(buffer, 0,"我是附加的参数",new CompletionHandler<Integer,String>(){

			@Override
			public void completed(Integer result, String attachment) {
				System.out.println("public void completed(Integer result,String attachment) result="+result+"attachment"+attachment);
			}

			@Override
			public void failed(Throwable exc, String attachment) {
			System.out.println("public void failed(Throwable exc,String attachment) attachment="+attachment);
			System.out.println("getMessage="+exc.getMessage());
			}

			
		});
		channel.close();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		}
		byte[] byteArray = buffer.array();
		for(int i = 0;i<byteArray.length;i++) {
			System.out.println((char)byteArray[i]);
		}
	}

}
运行结果:
public void completed(Integer result,String attachment) result=3attachment我是附加的参数
1
2
3

6.1.9 数据写入方式1

public class WriteTest {

	public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
		
		Path path = Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
		ByteBuffer buffer = ByteBuffer.wrap("abcde".getBytes());
		Future<Integer> future = channel.write(buffer, channel.size());
		System.out.println("length="+future.get());
		channel.close();
		

	}

}

6.1.10 数据写入方式2

public class WriteTest2 {

	public static void main(String[] args) throws IOException {

		Path path = Paths.get("a.txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
		ByteBuffer buffer = ByteBuffer.wrap("abcde".getBytes());
		channel.write(buffer, channel.size(),"我是附加的数据",new CompletionHandler<Integer,String>(){

			@Override
			public void completed(Integer result, String attachment) {
				System.out.println("public void completed(Integer result,String attachment) result="+result+"attachment"+attachment);
			}

			@Override
			public void failed(Throwable exc, String attachment) {
			System.out.println("public void failed(Throwable exc,String attachment) attachment="+attachment);
			System.out.println("getMessage="+exc.getMessage());
			}

			
		});
		channel.close();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		}
		
	}

}

6.2 AsynchronousServerSocketChannel和AsynchronousSocketChannel类的使用

AsynchronousServerSocketChannel类是面向流的侦听套接字的异步通道。一个AsynchronousServerSocketChannel通道是通过调用此类的open()方法创建。新创建的AsnchronousServerSocketChannel已打开但尚未绑定。它可以绑定本地地址,并通过调用bind()方法来配置侦听连接。一旦绑定,accept()方法被用来启动接受连接到通道的Socket.尝试在未绑定通道上调用accept()方法将导致引发NotYetBoundException异常。

AsynchronousSocketChannel类是面向流的连接套接字的异步通道。使用AsynchronousSocketChannel类的open()方法创建的是未连接状态的AsynchronousSocketChannel对象,之后再使用connect()方法将未连接的AsynchronousSocketChannel变成已连接的AsynchronousSocket对象。

6.2.1 读数据

public abstact <A> void read(ByteBuffer dst,long timeout,TimeUnit unit,A attachment,CompletionHandler <Integer, ? super A> handler)方法的作用是将此通道中的字节序列读入给定的缓冲区。

6.2.2 写数据

public abstract void write(ByteBuffer src,long timeout,TimeUnit ,A attachment,CompletionHandler <Integer,? super A> handler)方法的作用是从给定缓冲区向此通道写入一个字节序列。

6.3 同步 异步 阻塞 与非阻塞之间的关系

在普通的InputStream OutputStream 就是 同步阻塞。因为执行当前读写任务一直是当前线程,并且读不到或写不出去就一直是阻塞的状态。阻塞的意思就是方法不返回,直到读到数据或写出数据为止。

NIO 属于同步非阻塞。当执行“serverSocketChannel.configureBlocking(false)”代码后也是一直由当前的线程在执行读写操作,但是读不到数据或者数据写不出去时读写方法就返回了,继续执行读或写后面的代码。

而异步当然就是指多个线程间的通信。例如,A线程发起一个读操作,这个读操作要B线程进行实现,A线程和B线程就是异步执行了。A线程还要继续做其他的事情,这时B线程开始工作,如果读不到数据,B线程就呈阻塞状态了,如果读到数据,就通知A线程,并且将拿到的数据交给A线程,这种情况是异步阻塞。

如果B读不到数据,B线程继续读后面的代码,直到读到数据时,B线程就通知A线程,将拿到的数据交给A线程。

从大的概念上来讲,同步和异步关注的是消息通信机制,阻塞与非阻塞关注的是程序在等待调用结果时的状态。文件通道永远都是阻塞的,补鞥呢设置成非阻塞模式。

首先一个IO操作其实分成了两个步骤:
1.发起I/O请求
2.实际的I/O请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值