Junit单元测试、NIO——程序员都在学

Junit单元测试

概述

单元:是指在java的某个方法或者某个类。
测试:写一段代码对象单元进行测试。

使用步骤

1、编写一个被测试类(业务类)
2、编写测试类
3、在测试类使用Junit单元测试框架来测试即可。
运行程序时在需要独立运行的方法上加上一个注解@Test

案例代码:

//被测试类
public class dog {
    public int  getSum(int a, int b, int c) {
        int sum = a + b + c;
        return sum;
    }
}
//测试类
public class Testdog {
    @Test
    //测试代码
    public void test1() {
        dog dd = new dog();
        int sum = dd.getSum(1, 2, 4);
        System.out.println(sum);
    }
}

Junit4常用注解

@Before:表示该方法会自动在每个@Test方法之前执行。
@After:表示该方法会自动在每个@Test方法之后执行。

@BeforeClass:表示该方法会自动在所有@Test方法之前执行。
@AfterClass:表示该方法会自动在所有@Test方法之后执行。

注意:@BeforeClass和@AfterClass必须修饰静态方法。

Junit5常用注解

@BeforeEach:相当于@Before
@AfterEach:相当于@After
@BeforeAll:相当于@BeforeClass
@AfterAll:相当于@AfterClass

注意:@BeforeAll和@AfterAll必须修饰静态方法。

NIO介绍

概述

阻塞:完成某个任务时,任务没有结束之前,当前线程无法向下继续执行。
非阻塞:完成某个任务时,不需要等待任务结束,当前线程立即可以继续向下执行。

同步与异步

同步可能是阻塞的,也可能是非阻塞的。
同步阻塞:完成某个任务时,任务没有结束之前,当前线程无法继续向下执行。
同步非阻塞:完成某个任务时,任务没有结束之前,当前线程立即继续向下执行,后期需要我们自己写其他代码来获取结果,

异步,一般来说都是非阻塞的。
异步非阻塞:完成某个任务时,任务没有结束之前,当前线程立即继续向下执行,后期不需要我们自己写其他代码来获取结果,任务完成后会自动通过其他机制把结果传递给我们。

BIO,NIO,AIO

BIO(传统的IO流):同步阻塞的IO。
NIO(新的IO):可以是同步阻塞,也可以是同步非阻塞的。
NIO2(也叫AIO):异步非阻塞的IO。

NIO引入

NIO——Buffer类(缓冲区)

Buffer概述

Buffer称为缓冲区,本质上就是一个数组。
操作步骤:
1、写入缓冲区(把数据保存到数组中)
2、调用flip方法(切换缓冲区的写模式和读模式)
3、读缓冲区(把数组中的数据读取出来)
4、调用clear或者compact方法(清空缓冲区或者清除已经读取过的数据)

Buffer分类

ByteBuffer:字节缓冲区
CharBuffer:字符缓冲区
Doubleuffer:Double缓冲区
FloatBuffer:Float缓冲区
IntBuffer:整型缓冲区
LongBuffer:长整型缓冲区
ShortBuffer:短整型缓冲区

如何创建ByteBuffer

 public static allocate(int capacity)//在堆区中申请一个固定字节大小的ByteBuffer缓冲区【间接】
 public static allocatDirect(int capacity)//在系统的内存申请一个固定字节大小的ByteBuffer缓冲区【直接】
 public static wrap(byte[]arr)//把一个字节数组直接包装成ByteBuffer缓冲区 
        //1、创建一个ByteBuffer
        ByteBuffer allocate = ByteBuffer.allocate(10);//在jvm的堆中
        //打印一下
        System.out.println(Arrays.toString(allocate.array()));
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10);//直接和操作系统申请
        byte[]bs=new byte[10];
        ByteBuffer wrap = ByteBuffer.wrap(bs);

从创建和销毁的角度看,间接缓冲区效率高;从操作缓冲区来看,直接缓冲去效率更高。

向ByteBuffer添加数据

1public ByteBuffer put (byte b)//添加一个字节
2public ByteBuffer put (byte[] b])//添加一堆字节
3public ByteBuffer put  (byte[] b]int startIndex,int len )//添加一堆字节的一部分
		//2、添加数据
        //添加一个字节
        allocate.put((byte) 10);
        allocate.put((byte) 20);
        allocate.put((byte) 30);
        //添加一堆字节
        byte[] bs = {40, 50, 60};
        allocate.put(bs);
        //添加一堆字节的一部分
        byte[] bs1 = {70, 80, 90};
        allocate.put(bs1, 1, 2);

容量——capacity

可以存的元素的最大数量,定义了之后,容量是不可变的。取值范围是(0——capacity)
public int capacity();//获取容量

		//获取容量
        int capacity = allocate.capacity();
        System.out.println("容量是:"+capacity);

限制——limit

是指第一个不能读取或写入的那个元素的索引。
作用是,相当于人为修改缓冲区的大小,实际上缓冲区大小没有改变,只是可访问的元素的个数变了。

        //限制,获取限制
        int limit = allocate.limit();
        System.out.println("当前缓冲区的限制" + limit);
        //修改限制,缓冲区的限制修改为3【3指的是索引】
        Buffer limit1 = allocate.limit(3);

位置——position

将要读取、写入的元素的索引。取值范围是(0——capacity)

        //获取当前位置——添加完数据后,位置会随着发送改变
        int position = allocate.position();
        System.out.println("当前位置"+position);
        //修改位置,会将之前位置的数据替换掉
        Buffer position1 = allocate.position(2);
    }

标记——mark

给当前的position记录下来,当调用reset()重置方法时,position会回到标记,取值范围是(0——position)

public class ByteBufferDemo1 {
    public static void main(String[] args) {
        //1、创建一个ByteBuffer
        ByteBuffer allocate = ByteBuffer.allocate(10);//在jvm的堆中
        //2、添加数据
        allocate.put((byte) 10);
        allocate.put((byte) 20);
        allocate.put((byte) 30);
        allocate.mark();//记录当前位置是3
        allocate.put((byte) 40);
        allocate.put((byte) 50);
        allocate.put((byte) 60);
        allocate.reset();//重置,把位置修改为刚刚的标记
        allocate.put((byte) 99);
        allocate.put((byte) 99);
        allocate.put((byte) 99);
        System.out.println(Arrays.toString(allocate.array()));//[10, 20, 30, 99, 99, 99, 0, 0, 0, 0]
    }
}

Channel通道

概述

跟IO流类似,可以通过Channel读写数据。不同点是:IO流有输入输出流,但是Channel只有一种,没有输入输出之分。
分类:
FileChannel 文件通道,读写文件的
DatgramChannel UDP通道
SocketChannel TCP协议中客户端的通道
ServerSocketChannel TCP协议中服务器端的通道

FileChannel类的基本使用

案例实现
复制文件:

public class FileChannelDemo {
    public static void main(String[] args) throws IOException {
        //复制文件
        File src = new File("1.txt");
        File dest = new File("2.txt");
        //创建文件的两个流
        FileInputStream fileInputStream = new FileInputStream(src);
        FileOutputStream fileOutputStream = new FileOutputStream(dest);
        //通道
        FileChannel fileInputStreamChannel = fileInputStream.getChannel();
        FileChannel outputStreamChannel = fileOutputStream.getChannel();
        //复制文件
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int len = 0;
        while ((len = fileInputStreamChannel.read(buffer)) != -1) {
            //切换模式
            buffer.flip();
            //开始写
            outputStreamChannel.write(buffer);
            //写完后重置buffer
            buffer.clear();
        }
        fileInputStreamChannel.close();
        outputStreamChannel.close();
        fileInputStream.close();
        fileOutputStream.close();
    }
}

FileChannel结合MappedByteBUffer实现高效读写

通过内存进行复制,实现高效读写,只适合复制2G以下的文件。

public class FileChanneldemo {
    public static void main(String[] args) throws IOException {
        //读写模式rw,只读模式r,
        RandomAccessFile srcfile = new RandomAccessFile("复制文件的路径", "r");
        RandomAccessFile desfile = new RandomAccessFile("", "rw");
        //获取通道
        FileChannel channel = srcfile.getChannel();
        FileChannel channel1 = desfile.getChannel();
        //获取文件大小
        int size = (int) channel.size();
        //建立映射字节缓冲区
        //map(模式,开始索引,字节数)
        MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
        MappedByteBuffer map1 = channel1.map(FileChannel.MapMode.READ_WRITE, 0, size);
        //复制文件
        long start = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            byte b = map.get(i);
            map1.put(i, b);
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时" + (end - start));
        //释放资源
        channel.close();
        channel1.close();
    }
}

ServerSocketChannel和SocketChannel实现连接

ServerSocketChannel创建阻塞的服务器通道

    public static void main(String[] args) throws IOException {
        //ServerSocket serve=new ServerSocket("8888");
        //创建服务器通道,绑定本地的某个端口号
        ServerSocketChannel open = ServerSocketChannel.open();
        open.bind(new InetSocketAddress(8888));
        System.out.println("服务器启动了。。。");
        //接受客户端通道
        SocketChannel accept = open.accept();
    }
}

ServerSocketChannel创建非阻塞的服务器通道

//同步非阻塞服务器通道
public class ServerSocketChannelDemo1 {
    public static void main(String[] args) throws IOException {
        //ServerSocket serve=new ServerSocket("8888");
        //创建服务器通道,绑定本地的某个端口号
        ServerSocketChannel open = ServerSocketChannel.open();
        //设置一下【设置为同步非阻塞】
        SelectableChannel selectableChannel = open.configureBlocking(false);
        open.bind(new InetSocketAddress(8888));
        System.out.println("服务器启动了。。。");
        //接受客户端通道
        SocketChannel accept = open.accept();
        //后续代码
        System.out.println("后续代码。。。");
    }
}

SocketChannel阻塞客户端通道

//同步阻塞客户端通道
public class SocketChannelDemo {
    public static void main(String[] args) throws IOException {
        //创建SocketChannel客户端对象
        SocketChannel open = SocketChannel.open();
        //连接服务器
        boolean connect = open.connect(new InetSocketAddress("127.0.0.1", 8888));
        //后续代码
        System.out.println("后续代码");
    }
}

SocketChannel非阻塞客户端通道

//同步非阻塞客户端通道
public class SocketChannel1 {
    public static void main(String[] args) throws IOException, InterruptedException {
        //创建SocketChannel客户端对象
        SocketChannel open = SocketChannel.open();
        //设置一下
        SelectableChannel selectableChannel = open.configureBlocking(false);
        while (true) {
            //连接服务器
            try {
                boolean connect = open.connect(new InetSocketAddress("127.0.0.1", 8888));
                //后续代码
                System.out.println("后续代码");
                if (connect) {
                    System.out.println("和服务器进行交互");
                }
            } catch (Exception e) {
                System.out.println("两秒后再次尝试");
                Thread.sleep(2000);
            }
        }
    }
}

SocketChannel和ServerSocketChannel的通信

使用阻塞模式案例代码:

//服务器端
public class ServerSocketChannelDemo01 {
    public static void main(String[] args) throws IOException {
        //创建对象去连接
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8888));
        SocketChannel accept = serverSocketChannel.accept();
        System.out.println("有客户端连接了");
        //读取数据
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        int read = accept.read(byteBuffer);
        //打印数据
        byteBuffer.flip();//先把byteBuffer切换为读模式
        String string = new String(byteBuffer.array(), 0, read);
        System.out.println("客户端说:" + string);
        //回数据
        ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);
        ByteBuffer put = byteBuffer1.put("hello我是服务器".getBytes());
        //切换写模式
        byteBuffer1.flip();
        accept.write(put);
        //释放资源
        serverSocketChannel.close();
        serverSocketChannel.close();
    }
}
//客户端
public class SocketDemo02 {
    public static void main(String[] args) throws IOException {
        //创建SocketChannel对象
        //去连接
        SocketChannel socketChannel = SocketChannel.open();
        boolean connect = socketChannel.connect(new InetSocketAddress("", 888));
        //判断
        if (connect) {
            //发送数据
            System.out.println("连接成功");
            ByteBuffer wrap = ByteBuffer.wrap("你好,我是客户端通道".getBytes());
            socketChannel.write(wrap);
            //读取数据
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int read = socketChannel.read(buffer);
            buffer.flip();
            System.out.println(new String(buffer.array(), 0, read));
            socketChannel.close();
        }
    }
}

小结

现在所经历的一切,都将会作为以后步入社会的基石!

发布了16 篇原创文章 · 获赞 2 · 访问量 410
App 阅读领勋章
微信扫码 下载APP
阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 1024 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览