主頁 > 後端開發 > 【序列化與反序列化】關于序列化與反序列化MessagePack的實踐

【序列化與反序列化】關于序列化與反序列化MessagePack的實踐

2023-07-04 07:42:53 後端開發

  • 在進行序列化操作之前,我們還對系統進行壓測,通過jvisualvm分析cpu,執行緒,垃圾回收情況等;運用火焰圖async-profiler分析系統性能,找出程式中占用CPU資源時間最長的代碼塊,
  • 代碼放置GitHub:https://github.com/nateshao/leetcode/tree/main/source-code/src/main/java/com/nateshao/source/code/serializable

1.什么是序列化與反序列化?

聊到序列化與反序列化,先看看這個這個是什么或者是干嘛的

定義:序列化是指把物件轉換為位元組序列的程序;反序列化是指把位元組序列恢復為物件的程序;

一般都會知道有兩個目的:物件持久化網路傳輸

  1. 物件持久化,實作了資料的持久化,通過序列化可以把資料永久的保存在硬碟上;
  2. 網路傳輸,我們知道網路傳輸的是位元組序列,那么利用序列化實作遠程通信,即在網路上傳遞物件的位元組序列, (序列化與反序列化則實作了 行程通信間的物件傳送,發送方需要把這個Java物件轉換為位元組序列,才能在網路上傳送;接收方則需要把位元組序列再恢復為Java物件)

總結:序列化的目的是將物件變成位元組序列,這樣一來方便持久化存盤到磁盤,避免程式運行結束后物件就從記憶體里消失,另外位元組序列也更便于網路運輸和傳播

2.選擇序列化技術有哪些維度

這里并不是說哪個是最好,只能說是各有千秋,所以面對不同的背景采用不同的技術方案,

在同等情況下,編碼后的位元組陣列越大,存盤占空間,存盤硬體成本高,網路傳輸時也占帶寬,導致系統的吞吐量降低,

  1. 開發作業量和難度,作業量越少越好對吧,發揮的價值最大,
  2. 性能:需要考慮性能需求,序列化的速度和性能越高越好,
  3. 是否支持跨語言,支持的語言種類是否豐富,
  4. 安全性:對于安全性的需要考量,JDK序列化可能有卡死執行緒的漏洞,
  5. 占用空間大小:序列化的結果所占用的空間大小,序列化后的位元組資料通常會持久化到硬碟(占用存盤資源)或者在網路上傳輸給其他服務器(占用帶寬資源),這個指標當然是越小越好,
  6. 可維護性:技術流行程式,越流行的技術可維護性就越高,維護成本會越低,

3.為什么采用位元組序列MessagePack,有什么依據?

這個要結合當時的專案背景了,當時的專案痛點是:

  1. 老專案的結構調整比較大,交易性能上不去,所以先采取細節方面的優化,MessagePack是滿足性能要求
  2. 老系統業務變化不多,MessagePack是滿足要求
  3. 序列化反序列化效率高(比json快一倍),檔案體積小,比json小一倍,MessagePack是滿足要求

所以,存在MessagePack也有不好的地方,如果是針對業務變化比較多,那就不適合,需要比較不同的版本,然后選擇不同版本去決議,

我在京東內部文章有看到,參考的MessagePack反序列化出現了一些線上的問題,原因是:新增了一些欄位導致反序列化失敗

這里對比了JDK(不支持跨語言),JSON,Protobuf,MessagePack幾種序列化的方式,

當然,還有其他的XML、Hessian、Kryo(不支持跨語言)、FST(不支持跨語言)Thrift等,

4.JDK序列化

JDK序列化是Java默認自帶的序列化方式,在Java中,一個物件要想實作序列化,實作Serializable介面或者Externalizable介面即可,其中Externalizable介面繼承自Serializable介面,

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name = null;
    private Integer age = null;
    private SerializeDemo01.Sex sex;
	//....
}

serialVersionUID版本控制的作用

  1. 序列化的時候serialVersionUID也會被寫入二進制序列
  2. 反序列化時會檢查serialVersionUID是否和當前類的serialVersionUID一致,不一致則會拋出InvalidClassException 例外(序列化之后給類增加欄位再反序列化的時候就會報錯)

serialVersionUID必須保證物體類在序列化前后嚴格一致,否則將會導致無法反序列化,

JDK默認的序列化機制,需要實作java.io.Serializable介面

  1. 序列化后的碼流太大:jdk序列化機制編碼后的二進制陣列大小竟然是二進制編碼的5.29倍,
  2. 不支持跨語言平臺呼叫, 性能較差(序列化后位元組陣列體積大)
  3. 序列化性能太低:java序列化的性能只有二進制編碼的6.17%左右,Java原生序列化的性能實在太差,

JDK默認的序列化機制很差,所以我們通常不會選擇Java默認序列化這種

5.JSON序列化

json格式也是常見的一種,但是在json在決議的時候非常耗時,而且json結構非常占記憶體,JSON不適合存數字,特別是DOUBLE

這里基于Fastjson ,加載maven依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.70</version>
</dependency>

序列化物件

利用JSON.toJSONString方法序列化物件:

UserVO user = ...;String text = JSON.toJSONString(user);

序列化陣列

利用JSON.toJSONString方法序列化陣列:

UserVO[] users = ...;String text = JSON.toJSONString(users);

序列化集合

利用JSON.toJSONString方法序列化集合(繼承至Collection,比如List、Set等集合):

List<UserVO> userList = ...;String text = JSON.toJSONString(userList);

序列化映射

利用JSON.toJSONString方法序列化映射:

Map<Long, UserVO> userMap = ...;String text = JSON.toJSONString(userMap, SerializerFeature.MapSortField);

其中,為了保證每次序列化的映射字串一致,需要指定序列化引數MapSortField進行排序,

序列化模板物件

利用JSON.toJSONString方法序列化模板物件:

Result<UserVO> result = ...;String text = JSON.toJSONString(result);

代碼

package com.nateshao.source.code.serializable.json_Serializable.serializable;

import com.alibaba.fastjson.annotation.JSONField;
/**
 * @date Created by 邵桐杰 on 2023/2/25 17:11
 * @微信公眾號 千羽的編程時光
 * @博客 https://nateshao.gitlab.io
 * @GitHub https://github.com/nateshao
 * Description:
 */
public class User {
    /**
     * @JSONField 作用:自定義物件屬性所對應的 JSON 鍵名
     * @JSONField 的作用物件:
     * 1. Field
     * 2. Setter 和 Getter 方法
     * 注意:
     * 1. 若屬性是私有的,必須要有 set 方法,否則反序列化會失敗,
     * 2. 若沒有 @JSONField 注解,則直接使用屬性名,
     */
    @JSONField(name = "NAME")
    private String name;
    @JSONField(name = "AGE")
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

序列化ObjectTest

package com.nateshao.source.code.serializable.json_Serializable.serializable;

import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @date Created by 邵桐杰 on 2023/2/25 17:12
 * @微信公眾號 千羽的編程時光
 * @博客 https://nateshao.gitlab.io
 * @GitHub https://github.com/nateshao
 * Description:
 */
public class ObjectTest {
    private static List<User> userList = new ArrayList<User>();

    @BeforeAll
    public static void setUp() {
        userList.add(new User("千羽", 18));
        userList.add(new User("千尋", 19));
    }

    @DisplayName("序列化物件")
    @Test
    public void testObjectToJson() {
        String userJson = JSON.toJSONString(userList.get(0));
        System.out.println(userJson);  // {"AGE":18,"NAME":"千羽"}
    }

    @DisplayName("序列化集合")
    @Test
    public void testListToJson() {
        String userListJson = JSON.toJSONString(userList);
        System.out.println(userListJson);  // [{"AGE":18,"NAME":"千羽"},{"AGE":19,"NAME":"千尋"}]
    }

    @DisplayName("序列化陣列")
    @Test
    public void testArrayToJson() {
        User[] userArray = new User[5];
        userArray[0] = new User("zhangsan", 20);
        userArray[1] = new User("lisi", 21);
        String userArrayJson = JSON.toJSONString(userArray);
        System.out.println(userArrayJson);  // [{"AGE":20,"NAME":"zhangsan"},{"AGE":21,"NAME":"lisi"},null,null,null]
    }

    @DisplayName("序列化映射")
    @Test
    public void testMapToJson() {
        Map<Integer, User> userMap = new HashMap<Integer, User>();
        userMap.put(1, new User("xiaotie", 10));
        userMap.put(2, new User("xiaoliu", 11));
        String userMapJson = JSON.toJSONString(userMap);
        System.out.println(userMapJson);  // {1:{"AGE":10,"NAME":"xiaotie"},2:{"AGE":11,"NAME":"xiaoliu"}}
    }
}

反序列化UN_ObjectTest

package com.nateshao.source.code.serializable.json_Serializable.un_serializable;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @date Created by 邵桐杰 on 2023/2/25 17:16
 * @微信公眾號 千羽的編程時光
 * @博客 https://nateshao.gitlab.io
 * @GitHub https://github.com/nateshao
 * Description:
 */
public class UN_ObjectTest {
    @DisplayName("反序列化物件")
    @Test
    public void testJsonToObject() {
        String text = "{"age":18,"name":"千羽"}";
        User user = JSON.parseObject(text, User.class);
        System.out.println(user);  // User{name='千羽', age=18}
    }

    @DisplayName("反序列化陣列")
    @Test
    public void testJsonToArray() {
        String text = "[{"age":18,"name":"千羽"}, {"age":19,"name":"千尋"}]";
        User[] users = JSON.parseObject(text, User[].class);
        System.out.println(Arrays.toString(users));  // [User{name='千羽', age=18}, User{name='千尋', age=19}]
    }

    @DisplayName("反序列化集合")
    @Test
    public void testJsonToCollection() {
        String text = "[{"age":18,"name":"千羽"}, {"age":19,"name":"千尋"}]";
        // List 集合
        List<User> userList = JSON.parseArray(text, User.class);
        System.out.println(Arrays.toString(userList.toArray()));  // [User{name='千羽', age=18}, User{name='千尋', age=19}]
        // Set 集合
        Set<User> userSet = JSON.parseObject(text, new TypeReference<Set<User>>() {
        });
        System.out.println(Arrays.toString(userSet.toArray()));  // [User{name='千尋', age=19}, User{name='千羽', age=18}]
    }

    @DisplayName("反序列化映射")
    @Test
    public void testJsonToMap() {
        String text = "{1:{"age":18,"name":"千羽"}, 2:{"age":19,"name":"千尋"}}";
        Map<Integer, User> userList = JSON.parseObject(text, new TypeReference<Map<Integer, User>>() {
        });
        for (Integer i : userList.keySet()) {
            System.out.println(userList.get(i));
        }
        /*
            User{name='千羽', age=18}
            User{name='千尋', age=19}
         */
    }
}

json序列化總結

  • 好處

    1. 簡單易用開發成本低
    2. 跨語言
    3. 輕量級資料交換
    4. 非冗長性(對比xml標簽簡單括號倍訓)
  • 缺點

    1. 體積大,影響高并發
    2. 無版本檢查,自己做兼容
    3. 片段的創建和驗證程序比一般的XML復雜
    4. 缺乏命名空間導致資訊混合

6.Protobuf

Protobuf是谷歌推出的,是一種語言無關、平臺無關、可擴展的序列化結構資料的方法,它可用于通信協議、資料存盤等,序列化后體積小,一般用于對傳輸性能有較高要求的系統,前期需要額外配置環境變數,學習他的語法也是需要時間,

但是要使用Protobuf會相對來說麻煩一些,因為他有自己的語法,有自己的編譯器,如果需要用到的話必須要去投入成本在這個技術的學習中

Protobuf有個缺點就是傳輸的每一個類的結構都要生成相對應的proto檔案,如果某個類發生修改,還要重新生成該類對應的proto檔案,另外,Protobuf物件冗余,欄位很多,生成的類較大,占用空間,維護成本較高,

// 宣告語法,不顯示宣告默認是2.0的語法,
syntax = "proto3";
// 指定模板類的包路徑
option java_package = "com.test.basic.java.serialize.proto.dto";
// 指定模板類的名稱,名稱必須是有實際業務意義的
option java_outer_classname = "UserProto";

// 定義用戶物件
message User {
  // 名字
  string name = 1;
  // 年齡
  int32 age = 2;
}
// 宣告語法,不顯示宣告默認是2.0的語法,
syntax = "proto3";
// 指定模板類的包路徑
option java_package = "com\nateshao\source\code\serializable\protobuf_Serializable\User.proto";
// 指定模板類的名稱,名稱必須是有實際業務意義的
option java_outer_classname = "UserProto";

// 定義用戶物件
message User {
  // 名字
  string name = 1;
  // 年齡
  int32 age = 2;
}

7.MessagePack(推薦)

  1. 序列化反序列化效率高(比json快一倍),檔案體積小,比json小一倍,
  2. 兼容json資料格式
  3. 跨語言,多語言支持(超多)

不好的地方:

  1. 缺乏復雜模型支持,msgpack對復雜的資料型別(List、Map)支持的不夠,序列化沒有問題,但是反序列化回來就很麻煩,尤其是對于java開發人員,
  2. 維護成本較高,msgpack通過value的順序來定位屬性的,需要在不同的語言中都要維護同樣的模型以及模型中屬性的順序,
  3. 不支持模型嵌套,msgpack無法支持在模型中包含和嵌套其他自定義的模型(如weibo模型中包含comment的串列),

上手

通過配置msgpack的maven依賴

<dependency>
    <groupId>org.msgpack</groupId>
    <artifactId>msgpack</artifactId>
    <version>0.6.12</version>
</dependency>

封裝MsgPackTemplate抽象類,對原有msgpack進行二次加工,比如int,Short,Byte,BigDecimal進行read和write處理

MsgPackTemplate.java

package com.nateshao.source.code.serializable.msgpack_Serializable;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;

import org.msgpack.packer.Packer;
import org.msgpack.template.CharacterTemplate;
import org.msgpack.template.Template;
import org.msgpack.unpacker.Unpacker;
/**
 * @date Created by 邵桐杰 on 2023/2/25 23:11
 * @微信公眾號 千羽的編程時光
 * @博客 https://nateshao.gitlab.io
 * @GitHub https://github.com/nateshao
 * Description:
 */
public abstract class MsgPackTemplate <T> implements Template<T> {

    public void write(Packer pk, T v) throws IOException {
        write(pk, v, false);
    }

    public T read(Unpacker u, T to) throws IOException {
        return read(u, to, false);
    }

    public BigDecimal readBigDecimal(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }

        String temp = u.readString();
        if (temp != null) {
            return new BigDecimal(temp);
        }
        return null;
    }

    public Date readDate(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }

        long temp = u.readLong();
        if (temp > 0) {
            return new Date(temp);
        }
        return null;
    }

    public String readString(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readString();
    }

    public Integer readInteger(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readInt();
    }

    public Byte readByte(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readByte();
    }

    public Short readShort(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readShort();
    }

    public Float readFloat(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readFloat();
    }

    public Double readDouble(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readDouble();
    }

    public Character readCharacter(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.read(CharacterTemplate.getInstance());

    }

    public Long readLong(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readLong();
    }

    public Boolean readBoolean(Unpacker u) throws IOException {
        if (u.trySkipNil()) {
            return null;
        }
        return u.readBoolean();
    }




    public void writeBigDecimal(Packer pk, BigDecimal v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.toString());
        }
    }

    public void writeDate(Packer pk, Date v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.getTime());
        }
    }

    public void writeString(Packer pk, String v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v);
        }
    }

    public void writeInt(Packer pk, int v) throws IOException {
        pk.write(v);
    }

    public void writeInteger(Packer pk, Integer v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.intValue());
        }
    }

    public void writeByte(Packer pk, Byte v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.byteValue());
        }
    }

    public void writeShort(Packer pk, Short v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.shortValue());
        }
    }

    public void writeFloat(Packer pk, Float v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.floatValue());
        }
    }

    public void writeDouble(Packer pk, Double v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.doubleValue());
        }
    }

    public void writeCharacter(Packer pk, Character v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.charValue());
        }

    }

    public void writeLong(Packer pk, Long v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.longValue());
        }
    }

    public void writeLong(Packer pk, long v) throws IOException {
        pk.write(v);
    }

    public void writeBoolean(Packer pk, Boolean v) throws IOException {
        if (v == null) {
            pk.writeNil();
        } else {
            pk.write(v.booleanValue());
        }
    }
}

然后針對物體類進行讀和寫的序列化與反序列化操作,

User.java

package com.nateshao.source.code.serializable.msgpack_Serializable;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private static final long serialVersionUID = 4719921525393585541L;
    protected String id;
    private String userID;
    private String type;
    private BigDecimal rate;
    private Date createTime;
    private Date UpdateTime;
}

UserTemplate.java

package com.nateshao.source.code.serializable.msgpack_Serializable;

import org.msgpack.packer.Packer;
import org.msgpack.unpacker.Unpacker;

import java.io.IOException;

/**
 * protected String id;
 * private String userID;
 * private String type;
 * private BigDecimal rate;
 * private Date createTime;
 * private Date UpdateTime;
 */
public class UserTemplate extends MsgPackTemplate<User> {
    public void write(Packer packer, User user, boolean b) throws IOException {
        if (user == null) {
            packer.write(user);
            return;
        }
        // 欄位保持一致
        writeString(packer, user.id);
        writeString(packer, user.getUserID());
        writeString(packer, user.getType());
        writeBigDecimal(packer, user.getRate());
        writeDate(packer, user.getCreateTime());
        writeDate(packer, user.getUpdateTime());

    }

    public User read(Unpacker unpacker, User user, boolean req) throws IOException {
        if (!req && unpacker.trySkipNil()) {
            return null;
        }
        if (unpacker == null) return new User();
        user.setId(readString(unpacker));
        user.setUserID(readString(unpacker));
        user.setType(readString(unpacker));
        user.setRate(readBigDecimal(unpacker));
        user.setCreateTime(readDate(unpacker));
        user.setUpdateTime(readDate(unpacker));
        return user;
    }
}

參考文獻:

  • 官網:MessagePack: It's like JSON. but fast and small:https://msgpack.org/)
  • msgpack-java:https://github.com/msgpack/msgpack-java
  • MessagePack for C#譯文:快速序列化組件MessagePack介紹 - 曉晨Master - 博客園:https://www.cnblogs.com/stulzq/p/8039933.html
  • 原理分析和使用:https://www.jianshu.com/p/8c24bef40e2f
  1. https://blog.csdn.net/wzngzaixiaomantou/article/details/123031809
  2. https://blog.csdn.net/weixin_44299027/article/details/129050484
  3. https://www.cnblogs.com/juno3550/p/15431623.html
  4. Protobuf:https://blog.csdn.net/wxw1997a/article/details/116755542

作者:京東零售 邵桐杰

來源:京東云開發者社區

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556517.html

標籤:其他

上一篇:Java執行緒池基礎介紹

下一篇:返回列表

標籤雲
其他(162011) Python(38266) JavaScript(25520) Java(18286) C(15238) 區塊鏈(8275) C#(7972) AI(7469) 爪哇(7425) MySQL(7281) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5876) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4609) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1985) HtmlCss(1983) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1882) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 【序列化與反序列化】關于序列化與反序列化MessagePack的實踐

    序列化的目的是將物件變成位元組序列,這樣一來方便持久化存盤到磁盤,避免程式運行結束后物件就從記憶體里消失,另外位元組序列也更便于網路運輸和傳播 ......

    uj5u.com 2023-07-04 07:42:53 more
  • Java執行緒池基礎介紹

    一、執行緒池的優點 1、執行緒池能夠復用已經創建了的執行緒來執行任務,從而降低了頻繁創建和銷毀執行緒所帶來的資源消耗; 2、任務創建完成時,不必等待執行緒的創建,能夠立即執行,提高了任務回應的速度。 二、創建執行緒池的七大核心引數 1、corePoorSize 核心執行緒數 執行緒池中長期存活的執行緒數量。一般情況下 ......

    uj5u.com 2023-07-04 07:42:42 more
  • rocketmq-console基本使用

    # rocketmq-console基本使用 作用:rocketmq-console是rocketmq的一款可視化工具,提供了mq的使用詳情等功能。 ## 一、安裝部署 > 下載rocketmq組件 **rocketmq**:[下載地址](https://rocketmq.apache.org/zh ......

    uj5u.com 2023-07-04 07:42:22 more
  • JavaCV的攝像頭實戰之十三:年齡檢測

    ### 歡迎訪問我的GitHub > 這里分類和匯總了欣宸的全部原創(含配套原始碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 本篇概覽 - 本文是《JavaCV的攝像頭實戰》系列的 ......

    uj5u.com 2023-07-04 07:36:35 more
  • 提升性能的利器:深入決議SectionReader

    # 一. 簡介 本文將介紹 Go 語言中的 `SectionReader`,包括 `SectionReader`的基本使用方法、實作原理、使用注意事項。從而能夠在合適的場景下,更好得使用`SectionReader`型別,提升程式的性能。 # 二. 問題引入 這里我們需要實作一個基本的HTTP檔案服 ......

    uj5u.com 2023-07-03 07:38:51 more
  • 初識識別符號

    關鍵字 abstractassertbooleanbreakbyte case catch char class const continue default do double else enum extends final finally float for goto if implementi ......

    uj5u.com 2023-07-03 07:38:47 more
  • [滲透測驗]—7.4 逆向工程和二進制破解技術

    在本章節中,我們將深入學習逆向工程和二進制破解技術。我們將盡量詳細、通俗易懂地講解,并提供盡可能多的實體。 ## 1.1 逆向工程概述 逆向工程是指從軟體的二進制檔案中提取資訊,以了解其作業原理和設計思路的程序。逆向工程的主要目的是對軟體進行分析、除錯、修改等操作,以實作特定目的(如安全分析、病毒分 ......

    uj5u.com 2023-07-03 07:38:41 more
  • Java雜記————object.getClass()和object.class以及Java中的t

    不說廢話,直接上干貨: (注意大小寫:object為物件,Object為類) 1,object.getClass()它是Object類的實體方法,回傳一個物件運行時的類的Class物件,換句話說,它回傳的是物件具體型別的類物件。 2,Object.class 這是java語言的一種語法糖,用來回傳一 ......

    uj5u.com 2023-07-03 07:38:33 more
  • 基于嵌入式Tomcat的War包啟動器

    # 前言 最近針對java專案的部署方式進行整理,jenkins/tomcat/windows工具/linux腳本/web部署平臺等等 發現war包通過tomcat部署比較繁瑣,等待時間長,配置規則復雜對于小白很不友好,也難以接入到自定義的部署工具/平臺中 之前開發的Jar包部署平臺是servlet ......

    uj5u.com 2023-07-03 07:38:28 more
  • 【numpy基礎】--陣列索引

    陣列索引是指在`numpy`陣列中參考特定元素的方法。`numpy`的陣列索引又稱為`fancy indexing`,比其他編程語言的索引強大很多。 # 1. 選取資料 numpy的索引除了像其他語言一樣選擇一個元素,還可以間隔著選取多個元素,也可以用任意的順序選取元素。 比如一維陣列: ```py ......

    uj5u.com 2023-07-03 07:37:24 more