Pesquisa sobre os princípios e implementação de cópia zero e cópia profunda em Java

Cópia profunda e cópia zero são dois conceitos amplamente utilizados em Java para cópia de objetos e otimização de transferência de dados, respectivamente. Os princípios desses dois conceitos serão apresentados em detalhes abaixo e serão fornecidos exemplos de código Java correspondentes.

cópia profunda

  1. Princípio da cópia profunda (cópia profunda): a cópia profunda consiste em criar uma cópia completamente independente de um objeto, incluindo o próprio objeto, atributos de tipo de referência e subobjetos. A cópia profunda pode ser obtida por meio de serialização e desserialização.

Primeiro, você precisa garantir que o objeto a ser copiado e as classes referenciadas nele implementem a interface Serializable. Em seguida, as operações de serialização e desserialização são concluídas gravando objetos no fluxo de saída e lendo no fluxo de entrada. Dessa forma, você pode obter uma cópia totalmente nova do objeto, e o objeto original e o objeto copiado não têm influência um sobre o outro.

Uma maneira comum de implementar cópia profunda é por meio da serialização e desserialização. As etapas específicas são as seguintes:

  • Primeiro, você precisa gravar o objeto original em um fluxo de saída (como ObjectOutputStream), convertendo o objeto em uma sequência de bytes.
  • Em seguida, a sequência de bytes é lida no fluxo de saída e desserializada em um novo objeto por meio do fluxo de entrada (como ObjectInputStream). Este novo objeto é independente do objeto original e suas propriedades e subobjetos são copiados de forma independente.

Este método pode garantir que o objeto de cópia profunda e suas propriedades e subobjetos referenciados sejam todos novos, mas também pode envolver problemas como referências circulares no gráfico do objeto, que requerem tratamento especial. Além disso, o objeto copiado e a classe a que ele se refere precisam implementar a interface Serializable para realizar operações de serialização e desserialização.

import java.io.*;

class Student implements Serializable {
    
    
    private String name;
    private int age;

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    // Getters and setters here...

    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class DeepCopyExample {
    
    
    public static void main(String[] args) {
    
    
        Student original = new Student("John", 20);

        // 深拷贝
        Student copy = deepCopy(original);

        // 改变原始对象的属性值
        original.setName("Tom");
        original.setAge(25);

        System.out.println("Original: " + original);  // 输出 Original: Student{name='Tom', age=25}
        System.out.println("Copy: " + copy);          // 输出 Copy: Student{name='John', age=20}
    }

    public static <T extends Serializable> T deepCopy(T object) {
    
    
        try {
    
    
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.close();

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            T copy = (T) ois.readObject();
            ois.close();

            return copy;
        } catch (Exception e) {
    
    
            throw new RuntimeException("Deep copy failed", e);
        }
    }
}

No exemplo acima, uma Studentclasse é criada como o objeto a ser copiado. deepCopy()O método usa serialização e desserialização para realizar cópia profunda. Primeiro, o objeto original é gravado no fluxo de saída da matriz de bytes ( ) e, em seguida, desserializado ByteArrayOutputStreampor meio do fluxo de entrada da matriz de bytes ( ) para obter uma cópia totalmente nova do objeto.ByteArrayInputStream

cópia zero

  1. Princípio de cópia zero: cópia zero é uma tecnologia de otimização usada para reduzir ou evitar cópias desnecessárias de dados durante a transmissão de dados. Em Java, os métodos comuns de cópia zero incluem o uso de arquivos mapeados em memória e NIO.

  2. Cópia zero: Cópia zero é uma tecnologia de otimização usada para reduzir ou evitar operações desnecessárias de cópia de dados durante a transmissão de dados. Ele melhora a eficiência e o desempenho da transferência de dados, transferindo dados diretamente de um espaço de endereço para outro, sem copiar no meio.

Em Java, a cópia zero geralmente é usada para lidar com operações de E/S, como transferência de arquivos, transferência de rede, etc. Seu princípio é utilizar as características do sistema operacional para acessar diretamente a memória onde os dados estão localizados através da memória compartilhada (arquivos mapeados em memória) ou utilizar a tecnologia DMA (Direct Memory Access), reduzindo assim a cópia de dados entre o modo kernel e o modo kernel. modo de usuário.

A forma específica de implementar cópia zero depende do cenário e da API utilizada. A seguir estão duas implementações comuns de cópia zero:

  • Arquivos mapeados na memória: use FileChannel e MappedByteBuffer para mapear arquivos diretamente na memória para obter um efeito de cópia zero. O conteúdo dos arquivos pode ser manipulado diretamente na memória, evitando a cópia de dados durante a leitura e gravação.
  • Transmissão de rede com cópia zero: usando bibliotecas NIO (E/S sem bloqueio), como SocketChannel, combinadas com ByteBuffer, a transmissão de rede com cópia zero pode ser alcançada. Os dados podem ser lidos diretamente do buffer de rede para o buffer de memória direto do aplicativo ou gravados diretamente do buffer de memória para a rede, evitando a cópia de dados entre o modo de usuário e o modo kernel.

O uso da tecnologia de cópia zero pode melhorar significativamente a eficiência da transmissão de dados e reduzir a carga de trabalho da CPU. Especialmente em transmissão de dados em grande escala e ambientes de alta simultaneidade, a melhoria de desempenho é muito significativa.

  • Arquivos mapeados na memória: ao mapear arquivos diretamente na memória, você pode evitar a cópia de dados entre o modo de usuário e o modo kernel. Especificamente, ele pode ser usado  FileChannel e  implementado, e  os MappedByteBuffer métodos relacionados incluem  map(),, get()etc. put()Aqui está um exemplo:
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class ZeroCopyMemoryMappedFileExample {
    
    
    public static void main(String[] args) throws IOException {
    
    
        File file = new File("data.txt");
        String content = "This is the content to be written.";

        // 写入数据
        try (FileChannel channel = new RandomAccessFile(file, "rw").getChannel()) {
    
    
            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, content.length());
            buffer.put(content.getBytes());
        }

        // 读取数据
        try (FileChannel channel = new FileInputStream(file).getChannel()) {
    
    
            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
            byte[] data = new byte[(int) channel.size()];
            buffer.get(data);
            System.out.println(new String(data));
        }
    }
}

No exemplo acima, um objeto de arquivo filee o conteúdo a ser gravado são criados primeiro content. Use FileChannelpara abrir um canal de arquivo e use map()o método para mapear parte ou todo o conteúdo do arquivo em um buffer na memória MappedByteBuffer. Em seguida, put()o conteúdo é gravado no buffer por meio do método. Em seguida, reabra o canal do arquivo e use map()o método para mapear todo o conteúdo do arquivo para outro buffer na memória MappedByteBuffer. Finalmente, get()o conteúdo é lido do buffer em uma matriz de bytes por meio do método e a string é gerada.

Guess you like

Origin blog.csdn.net/weixin_44427181/article/details/132945656