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添加数据
1、public ByteBuffer put (byte b);//添加一个字节
2、public ByteBuffer put (byte[] b]);//添加一堆字节
3、public 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();
}
}
}
小结
现在所经历的一切,都将会作为以后步入社会的基石!