单例模式和NIO的学习

单例模式和NIO

单例模式

当前类只有一个对象,无法再重新创建当前类的对象

与反射违背

懒汉单例模式推导

整个代码运行周期内只有一个类对象

期望:从语法角度约束一些行为,目前创造对象过于简单。

解决方案:private修饰构造方法

但构造方法私有化后,类外没有操作构造方法的权限,没办法创造对象

解决方案:

需要方法来完成

  1. 该方法要求静态成员方法,没有对象,需要通过类名调用。
  2. 类外要求使用public修饰。
  3. 该方法需要得到一个SingleDog对象,返回值类型是SingleDog。
  4. 方法参数为无参数,构造方法也是无参。
  5. 方法名 getInstance public static SingleDog getInstance()。

期望:每一次调用方法都是new心得对象。new一次就不能new第二次,存在一个变量保存第一次new第项的空间首地址,并且永固就保存。
private static SingleDog sd = null;

需要判断SingleDog类型的静态成员变量 sd是否保存有之前创建的空间首地址。

期望 :在多线程情况下,也是安全的

解决方法:synchronized同步代码块, 最合适的锁对象依然是Single.class。

synchronized同步方法, static修饰静态方法的情况下,什么是锁对象?当前SingleDog类.class字节码文件。

  package com.qfedu.a_single;
  
  import java.util.concurrent.locks.Lock;
  import java.util.concurrent.locks.ReentrantLock;
  
  /**
   * SingleDog要求是一个单例类,整个代码运行周期内有且只有一个类对象
   *
   * @author Anonymous 2020/3/13 19:53
   */
  public class SingleDog {
      private static SingleDog sd = null;
  
      private SingleDog() {}
  
      public static SingleDog getInstance() {
  
          Lock lock = new ReentrantLock();
  
          lock.lock();
          if (null == sd) {
              sd = new SingleDog();
          }
          lock.unlock();
  
          return sd;
      }
  }

饥汉模式

package com.qfedu.a_single;

/**
 * 另一个单例模式
 *
 * @author Anonymous 2020/3/13 20:09
 */
public class SingleCat {
    /*
    static修饰,在代码的加载阶段创建完成
    并且使用final修饰,保存当前指向不可以改变
    private修饰类外无法直接获取,不能修改
     */
    private static final SingleCat sc = new SingleCat();

    private SingleCat() {

    }

    public static SingleCat getInstance() {
        return sc;
    }
}

NIO

NIO ==> New IO(新IO), Non-Block IO(非阻塞IO)

运行当前程序在处理IO事务时,不会影响其他程序的运行,可以在不使用多线程的情况下,满足IO操作要求。

三大核心部分:
	通道

		Channel

		文件操作,网络数据传递操作使用的通道

		缓冲。

		Buffer

		缓冲使用可以提供操作效率,减少不必要的

		读写次数。

	选择器

		Selector
常用API
java.nio.Buffer
Buffer缓冲区
ByteBuffer 字节缓冲 常用

ShortBuffer

IntBuffer

LongBuffer 

CharBuffer 字节缓冲 常用

FloatBuffer

DoubleBuffer

常用方法:

	public static ByteBuffer allocate(int capacity);

		按照指定的字节数分配对应的缓冲区空间,

		保存字节数据。

	public byte get(); 

		从字节缓冲区对象中读取一个byte类型数组

	public final Buffer flip();

		翻转缓冲区,回到缓冲区的开始位置。

	public static ByteBuffer wrap(byte[] arr);

		存入一个byte类型数组到缓冲区,会得到一	

		个新的ByteBuffer。

	public static ByteBuffer put(byte[] b);

		将字节数组存入缓冲区
Channel接口,通道接口
FileChannel 文件操作通道。

DatagramChannel UDP协议数据包操作的Channel

ServerSocketChannel TCP服务端ServerSocket对应	

Channel。

SocketChannel TCP客户端Socket对应Channel

首先操作文件。

public long read(ByteBuffer buffer);

	从通道中读取数据到ByteBuffer中

public long write(ByteBuffer buffer);

	从Buffer中写数据到通道中

public long transferFrom(ReadableByteChannel src, long position, long count) 

从指定srcChannel中,指定位置position开始,读取

count个元素,到当前通道中

文件复制操作。

public long	transferTo(long position, long count, WritableByteChannel target) 

将当前通道中的数据写入到target中,从当前通道的	

position位置开始,计数count。

package com.qfedu.b_niofile;

import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.Selector;

/**
 * NIO文件操作
 *
 * @author Anonymous 2020/3/13 20:30
 */
public class FileNioTest {

    /*
    通过NIO写入数据到文件中的操作
     */
    @Test
    public void testNioFileWrite() throws IOException {
        // 1. 文件操作字节输出流
        FileOutputStream fos = new FileOutputStream("E:/aaa/1.txt");

        // 2. 利用文件操作输出字节流对象获取对应的Channel通道
        FileChannel foc = fos.getChannel();

        // 3. 准备一个缓冲区 4KB缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024 * 4);

        // 4. 准备数据,放入缓冲区
        String str = "测试Test";
        buffer.put(str.getBytes());

        // 5. 存在缓冲区数据放入之后,缓冲区指针发生改变,到达存入数据的末尾
        buffer.flip();

        // 6. 缓冲区数据写入到通道中
        foc.write(buffer);

        // 7. 关闭资源
        fos.close();
    }

    @Test
    public void testNioFileRead() throws IOException {
        // 1. 文件字节操作输入流
        FileInputStream fis = new FileInputStream("E:/aaa/1.txt");

        // 2. FileChannel
        FileChannel fic = fis.getChannel();

        // 3. 准备缓冲
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        // 4. 从Channel读取数据保存到缓冲区中
        int read = fic.read(buffer);
        System.out.println(read);

        // 5. 展示数据
        System.out.println(new String(buffer.array(), 0, read));

        // 6. 关闭资源
        fis.close();
    }

    // 130
    @Test
    public void testCopyFile() throws IOException {
        long start = System.currentTimeMillis();
        // 1. 安排输出流和输入流
        FileInputStream fis = new FileInputStream("E:/aaa/1.mp4");
        FileOutputStream fos = new FileOutputStream("E:/aaa/2.mp4");

        // 2. 准备两个Channel
        FileChannel srcChannel = fis.getChannel();
        FileChannel dstChannel = fos.getChannel();

        // 3. 拷贝方法
        srcChannel.transferTo(0, srcChannel.size(), dstChannel);
        // dstChannel.transferFrom(srcChannel, 0, srcChannel.size());

        // 4. 关闭资源
        fos.close();
        fis.close();

        long end = System.currentTimeMillis();
        System.out.println("Time:" + (end - start));
    }

    // 300
    @Test
    public void testCopyUseBuffer() throws IOException {
        long start = System.currentTimeMillis();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/aaa/1.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/aaa/3.mp4"));

        int length = -1;
        byte[] buf = new byte[4 * 1024];

        while ((length = bis.read(buf)) != -1) {
            bos.write(buf, 0, length);
        }

        bos.close();
        bis.close();
        long end = System.currentTimeMillis();
        System.out.println("Time:" + (end - start));

        Selector
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值