niewj

niewj 查看完整档案

北京编辑山西农业大学  |  计算机应用 编辑大厂  |  Java程序员 编辑 www.niewj.com 编辑
编辑

遇见超乎想象的自己!

个人动态

niewj 回答了问题 · 9月25日

请教关于thymeleaf的模板导入路径问题

我记得路径一律用 @表达式, 你查查看 thymeleaf的文档

关注 2 回答 1

niewj 发布了文章 · 9月25日

netty学习笔记-(05)-netty之NIO的聊天室简易版

NIO 简易版聊天室

1. server端:

package com.niewj.niochat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by niewj on 2020/9/22 15:18
 */
public class NioChatServer {

    public static final int PORT = 7777;
    public static final int BUF_SIZE = 512;
    private Selector selector;
    private ServerSocketChannel serverChannel;

    public static void main(String[] args) throws IOException {
        NioChatServer server = new NioChatServer();
        server.init();
        server.listen();
    }

    private void listen() throws IOException {
        // 关联成功后 轮询监听客户端连接
        while (true) {
            // 阻塞方法: 直到有注册的事件发生
            int readyChannels = selector.select();
            if (readyChannels == 0) {
                continue;
            }
            // 收集监听的事件
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iter = keys.iterator();
            while (iter.hasNext()) {
                SelectionKey key = iter.next();

                if (key.isAcceptable()) {
                    // 处理-accept事件
                    handleAcceptable(key);
                }
                if (key.isReadable()) {
                    // 处理-read 事件
                    readDataFromSocket(key);
                }

                /** 注意每次 iter.remove():
                 * Selector不会自己移除SelectionKey实例, 必须在处理完Channel时自己移除。
                 * 下次该通道就绪时,Selector会再次将其放入已选择键集中。 */
查看原文

赞 0 收藏 0 评论 0

niewj 发布了文章 · 9月24日

java8的stream应用之-求3个班级的男生的平均身高中-最高的那个身高

1. 问题

川哥在群里出的题:

一共三个班级,每个班级的人数(男生,女生)不等,要求求出这三个班级的男生的平均身高中,最高的那个身高

2. 代码

package com.niewj.stream;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * 求3个班级(人数/男生/女生不等)的男生的平均身高中,最高的那个身高
 * <p>
 * Created by niewj on 2020/9/24 11:40 */public class StreamTest {
    public static void main(String[] args) {
        // 初始化3个年级
 Grade grade1 = new Grade("1年级");
        Grade grade2 = new Grade("2年级");
        Grade grade3 = new Grade("3年级");
        // 初始化数据 24个学生
 List<Student> studentList = initStudents(grade1, grade2, grade3);
        // 答题
 Optional<Double> max = studentList.stream()
                .filter(s -> "男".equals(s.getGender()))
                .collect(Collectors.groupingBy(Student::getGrade, Collectors.averagingDouble(Student::getHeight)))
                .values()
                .stream()
                .max(Double::compareTo);
        System.out.println(max.orElse(0.0));
    }
    private static List<Student> initStudents(Grade grade1, Grade grade2, Grade grade3) {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(grade1, "女", "张00", 160));
        studentList.add(new Student(grade2, "男", "张01", 179));
        studentList.add(new Student(grade3, "男", "张02", 172));
        studentList.add(new Student(grade1, "女", "张03", 162));
        studentList.add(new Student(grade2, "男", "张04", 170));
        studentList.add(new Student(grade3, "男", "张05", 162));
        studentList.add(new Student(grade2, "男", "张06", 175));
        studentList.add(new Student(grade1, "女", "张07", 162));
        studentList.add(new Student(grade2, "男", "张08", 172));
        studentList.add(new Student(grade3, "男", "张09", 176));
        studentList.add(new Student(grade2, "女", "张10", 159));
        studentList.add(new Student(grade1, "男", "张11", 172));
        studentList.add(new Student(grade2, "男", "张12", 177));
        studentList.add(new Student(grade3, "女", "张13", 170));
        studentList.add(new Student(grade2, "男", "张14", 172));
        studentList.add(new Student(grade1, "女", "张15", 166));
        studentList.add(new Student(grade2, "女", "张16", 166));
        studentList.add(new Student(grade3, "男", "张17", 190));
        studentList.add(new Student(grade2, "女", "张18", 172));
        studentList.add(new Student(grade1, "女", "张19", 160));
        studentList.add(new Student(grade2, "女", "张20", 155));
        studentList.add(new Student(grade2, "男", "张21", 172));
        studentList.add(new Student(grade2, "男", "张22", 169));
        studentList.add(new Student(grade1, "女", "张23", 170));
        return studentList;
    }
    @Data
 @AllArgsConstructor @NoArgsConstructor static class Student {
        private Grade grade;
        private String gender;
        private String sname;
        private int height;
    }
    @Data
 @AllArgsConstructor static class Grade {
        private String className;
    }
}

3. 小结:

Optional<Double> max = studentList.stream()
        .filter(s -> "男".equals(s.getGender()))
        .collect(Collectors.groupingBy(Student::getGrade, Collectors.averagingDouble(Student::getHeight)))
        .values()
        .stream()
        .max(Double::compareTo);
查看原文

赞 0 收藏 0 评论 0

niewj 回答了问题 · 9月24日

Unsafe类能否获取一个独立对象的offset(这个对象不是某个其他对象的field)?

这个问题来源于一个面试题: 就是通过调用一个方法: changeUser(u)
当 changeUser方法返回后, 能否就改变u的地址?
我们知道, 可以在方法内改变u的对象的内容; 但是能不能在里面通过Unsafe来改变u这个引用的指向呢?

关注 2 回答 2

niewj 回答了问题 · 9月22日

研究课题选择

人工智能与机器学习可学的现有公共框架和工具比较多,可参考的很多;
智能传感与控制, 可能更偏重某一个领域, 如果都是两眼一抹黑, 就找有方向感的, 或者有大佬带的得了;
做选择很痛苦, 选择了, 就只能超前努力了, 没有路也得自己踏出来一条~ 加油吧~

关注 2 回答 1

niewj 关注了问题 · 9月22日

Unsafe类能否获取一个独立对象的offset(这个对象不是某个其他对象的field)?

如题: Unsafe类能否获取一个独立对象的offset(这个对象不是某个其他对象的field)? 比如这个普通类User, 有一个对象:

@Data
public class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public static void main(String[] args) {
    // 1. 一个普通的独立User对象
    User u = new User("u1", 20);
    // 2. 获取Unsafe对象
    // 通过反射得到theUnsafe对应的Field对象
    Field field = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true); // 设置该Field为可访问
    Unsafe unsafe = (Unsafe) field.get(null); // 通过Field得到对应的对象,传入null是因为该Field为static

    // 3. ? 有没有什么方式获取到User的u对象的内存地址(offset)?
}
  1. 能否获取到u对象的内存地址?
  2. 或者, 有没有什么办法可以直接把u传入一个方法, 永久改变他的引用值?

关注 2 回答 2

niewj 提出了问题 · 9月21日

Unsafe类能否获取一个独立对象的offset(这个对象不是某个其他对象的field)?

如题: Unsafe类能否获取一个独立对象的offset(这个对象不是某个其他对象的field)? 比如这个普通类User, 有一个对象:

@Data
public class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public static void main(String[] args) {
    // 1. 一个普通的独立User对象
    User u = new User("u1", 20);
    // 2. 获取Unsafe对象
    // 通过反射得到theUnsafe对应的Field对象
    Field field = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true); // 设置该Field为可访问
    Unsafe unsafe = (Unsafe) field.get(null); // 通过Field得到对应的对象,传入null是因为该Field为static

    // 3. ? 有没有什么方式获取到User的u对象的内存地址(offset)?
}
  1. 能否获取到u对象的内存地址?
  2. 或者, 有没有什么办法可以直接把u传入一个方法, 永久改变他的引用值?

关注 2 回答 2

niewj 回答了问题 · 9月21日

如何在GitHub上大显身手?

您这是问? 还是答呢?~~!

关注 2 回答 1

niewj 发布了文章 · 9月20日

面试题之-Java中判断200==200为false但127==127为true的疑问

Java中判断200==200为false但127==127为true的疑问

1. 问题的引出

1.1 200==200为false吗?

代码:

package com.niewj.nio;

/**
 * Created by niewj on 2020/9/20 11:24
 */
public class Test {
    public static void main(String[] args) {
        Integer i1 = 127;
        Integer i2 = 127;
        System.out.println("包装类 127 == 127: "+ (i1 == i2));

        Integer i3 = 200;
        Integer i4 = 200;
        System.out.println("包装类 127 == 127: "+ (i3 == i4));

        int i5 = 200;
        int i6 = 200;
        System.out.println("非包装int型 200 == 200: " + (i5 == i6));
    }
}

控制台输出:

包装类 127 == 127: true
包装类 127 == 127: false
非包装int型 200 == 200: true

看现象得结论:

1). 原生类型的200==200为true

2). 包装类Integer的200==200为false

3). 包装类Integer的127==127为true

看结论得疑惑? why??

对象类型的==比较的不是 对象的内存地址吗? 怎么这两个对象难道是一个?? 下来我们找找原因:

1.2 为什么包装类127==127为true

翻开随身携带的记事本, 写着许多事, 都是关于你....你讨厌被冷漠....习惯被守候...

跑题了, 我们不唱歌!

翻开jdk的源码, Integer:829行:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

看代码能开出些许动过刀的嫌疑, 没错, 方法的文档注释里也说了:

1). -128到127的值被缓存

此方法将始终缓存范围为-128到127(包括在内)的值,并可能缓存此范围之外的其他值。

没错了, 这就是问题的原因, 辣么, 咋个实的现?

2. 问题的原因探究

Integer类内部有个static的内部类IntegerCache, 就是实现的原因:

2.1 IntegerCache的实现:

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

类的文档注释:

Cache to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive) as required by JLS. The cache is initialized on first usage. The size of the cache may be controlled by the -XX:AutoBoxCacheMax=<size> option. During VM initialization, java.lang.Integer.IntegerCache.high property may be set and saved in the private system properties in the sun.misc.VM class.

机器人翻译:

缓存以支持JLS要求的-128和127(包括)之间值自动装箱的对象标识语义。缓存在第一次使用时初始化。缓存的大小可以由-XX:AutoBoxCacheMax=<size>选项控制。在VM初始化期间,java.lang.Integer.IntegerCache。高属性可以设置和保存在私人系统的阳光属性。VM类。

2.2 IntegerCache类实现简析:

1). IntegerCache类特点:

  1. static class : 只随着类的加载, 初始化一次, 跟后续的不管多少个Integer的实例无关;
  2. static Integer cache[] : 所有Integer实例都可以共享的 cache;
  3. static int low=-128: 最小值为 -128;
  4. static int high; 最大值(static里有逻辑, 默认是127)
  5. static{}块中初始化逻辑

2). 着重分析下static{}块中初始化逻辑

sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high")

代码中读取了这个属性, 然后用它跟127比, 取大的, 作为最大缓存值;

关于这个属性的意义和操作空间, 我们在最后一部分详述:问题的逆转?! 部分

现在只要知道, 默认的话, 就是:

  1. 初始化了一个 static的Integer数组, 容量是256个, 存放的内容就是-128到127之间的值
  2. 我们在声明和初始化一个Integer变量的时候, 如果值的区间在 -128到127之间, 就会从这个cache数组中取;
  3. 由于这个cache数组是静态的, 所以所有的Integer的实例可以共享
  4. 所以, 包装类型的Integer 127==127 实际上都是这个cache中的第一次初始化的127的Integer对象, 必然是同一个, 就true了;
  5. 但是200就不一样了, cache的区间只有 -128到127, 200的并没有缓存, 所以会每次初始化新的Integer对象实例

3). Integer的-128到127之间的值被缓存, 非此区间的每次都是新实例对象;

3. 问题的扩展:Byte/Short/Long/Character

原因已经找到了, 我们该结束了? 不不不, 这可是一道面试题, 你不发挥发挥? 你不发挥可能就被挥发了....危....

Integer有缓存了, 那么其他的整数类型呢?

Byte/Short/Character/Long 会不会也是共犯?

我们揪出源码审问一下:

3.1 Byte的缓存-ByteCache

Byte类还没打就招了:

private static class ByteCache {
    private ByteCache(){}

    static final Byte cache[] = new Byte[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Byte((byte)(i - 128));
    }
}

由于Byte本身体弱能力有限, 看到刑拘就招认了; 我本身就只占一个字节, 也没什么花花肠子, 我坦白吧: 我甚至都不用什么属性配置类, 我的实现也很简单粗暴, 够用就行!

1). ByteChache实现了Byte中的-128到127的缓存

3.2 Short的缓存-ShortCache

Short占2个字节, 它的实现也简单粗暴, 够用就行, 不耍花花绕:

private static class ShortCache {
    private ShortCache(){}

    static final Short cache[] = new Short[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Short((short)(i - 128));
    }
}

1). ShortCache实现了Short中的-128到127的缓存

3.3 Long的缓存-LongCache:

Long可是占8个字节的, 壮的一匹! 但是实现也是简单粗暴, 纯情的壮汉一枚!

private static class LongCache {
    private LongCache(){}

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

1). LongCache实现了Long中的-128到127的缓存

3.4 Character的缓存CharacterCache:

Character表示, 我只有2个字节, 本身是要表示字符的, 表示数字就是兼职交个朋友, 我也很纯情:

private static class CharacterCache {
    private CharacterCache(){}

    static final Character cache[] = new Character[127 + 1];

    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Character((char)i);
    }
}

1). CharacterCache实现了Character中的-128到127的缓存

4. 问题有逆转?!

再看个程序:

package com.niewj.nio;

/**
 * -XX:AutoBoxCacheMax=256
 * System.out.println(sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"));
 * Created by niewj on 2020/9/19 0:24
 */
public class Test {
    public static void main(String[] args) {
        Integer i3 = 256;
        Integer i4 = 256;
        Integer i5 = 257;
        Integer i6 = 257;
        System.out.println("包装类 256 == 256: "+ (i3 == i4));
        System.out.println("包装类 257 == 257: "+ (i5 == i6));
    }
}

程序输出:

包装类 256 == 256: true
包装类 257 == 257: false

什么??!! 包装类Integer啊! 256==256怎么是true? 257==257怎么又是false?

鬼火?! what the shark! 啥情况?

没错, 我们在main方法的注释里已经标明了, 是在启动时, 加了JVM参数, 设置了:

-XX:AutoBoxCacheMax=256

所以此时, Integer缓存的范围就不是 -128到127了, 而是-128到256;

JVM给了Integer类一个操作空间, 可以扩大缓存的范围! 我们通过JVM参数扩大到256了, 所以256比较是同一个对象, 但是257就否了!

4.1 -XX:AutoBoxCacheMax此JVM参数可以扩大Integer里cache的上限值

1). 设置jvm参数: -XX:AutoBoxCacheMax=256

package com.niewj.nio;

public class Test {
    public static void main(String[] args) {
        Integer i3 = 256;
        Integer i4 = 256;
        Integer i5 = 257;
        Integer i6 = 257;
        System.out.println("包装类 256 == 256: "+ (i3 == i4));
        System.out.println("包装类 257 == 257: "+ (i5 == i6));

        System.out.println("java.lang.Integer.IntegerCache.high=\t" + sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"));
    }
}

控制台输出:

包装类 256 == 256: true
包装类 257 == 257: false
java.lang.Integer.IntegerCache.high=    256

可以看到, 这个参数已经被改了: java.lang.Integer.IntegerCache.high

2). -XX:AutoBoxCacheMax参数改的就是java.lang.Integer.IntegerCache.high的值

4.2 那么, Byte/Short/Long/Character这些类呢? 能扩容么

package com.niewj.nio;

public class Test {
    public static void main(String[] args) {
        Integer i1 = 256;
        Integer i2 = 256;
        System.out.println("Integer包装类 256 == 256: "+ (i1 == i2));

        Short s1 = 256;
        Short s2 = 256;
        System.out.println("Short包装类 256 == 256: "+ (s1 == s2));

        Long l1 = 256L;
        Long l2 = 256L;
        System.out.println("Long包装类 256 == 256: "+ (l1 == l2));

        Character c1 = 256;
        Character c2 = 256;
        System.out.println("Character包装类 256 == 256: "+ (c1 == c2));

        System.out.println("java.lang.Integer.IntegerCache.high=\t" + sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"));
    }
}

控制台输出:

Integer包装类 256 == 256: true
Short包装类 256 == 256: false
Long包装类 256 == 256: false
Character包装类 256 == 256: false
java.lang.Integer.IntegerCache.high=    256

其实从上面的代码分析我们也可以看出, 除了Integer, 其他的类都没有做参数读取; 都只用了127这个固定值;

1). 只有Integer的缓存127最大值可以参数修改

查看原文

赞 0 收藏 0 评论 0

niewj 发布了文章 · 9月19日

MySQL数据库表各种大小限制小结

本文所有条目总结均来自mysql5.6的官网英文文档:

table-size-limit

1. MySQL表的列数限制

1.1 MySQL硬性限制每个表最大4096个列

1.2 InnoDB存储引擎的约束: 每个表最大1017个列;

2. MySQL表的每行数据的限制

2.1 MySQL表限制row size最大 65535个字节

2.2 InnoDB限制row size最大半页, 默认页大小16K, 也就是 row size < 8K;

3. MySQL表总数据量的限制

3.1 一个表的总大小限制取决于操作系统的文件限制

1) windows fat32的话, 最大就是4G

如果要想超过4G, 在64位windows上使用NTFS ;

2) 其他的windows上的文件数的限制等

在Windows上,表空间文件的路径(包括文件名)不能超过MAX_PATH限制。

在Windows 10之前,MAX_PATH的限制是260个字符。从Windows 10 1607版本开始,常见的Win32文件和目录函数中删除了MAX_PATH限制,但是必须启用新的行为。

3.2 默认MyISAM数据和索引文件最大到256TB,但此限制可改为最大65536TB

3.3 InnoDB的表大小限制:64T(取决于页大小, 详见下5)

4. MySQL数据库的表个数:无限制(InnoDB允许40亿个表)

MySQL对表的数量没有限制。

底层文件系统可能对表示表的文件数量有限制。

单个存储引擎可能会施加特定于引擎的约束: InnoDB允许多达40亿个表

5. 综上-总结InnoDB的限制

5.1 MySQL5.6以后允许InnoDB表最多1017个列

5.2 一个InnoDB表最多允许64个二级索引

5.3 默认索引前缀长度最多767bytes

5.4 联合索引最多允许16个列, 多了报错

5.5 InnoDB的最大行大小为半页(小于8K-默认)

由于默认页大小为16K, 要求是小于half page size, 就是小于8K;

innodb_page_size可以通过这个修改为4K, 8K; 这样的话, rowsize 就限制为小于 2K, 4K了;

虽然InnoDB内部支持大于65,535字节的行大小,但MySQL本身对所有列的合并大小施加了65,535的行大小限制。-?跨页?另设置?

5.6 innoDB日志文件的最大组合大小是512G

5.7 InnoDB表空间大小限制64T(表空间最大大小也是表的最大大小)

最小表空间大小略大于10MB

最大表空间大小取决于InnoDB的页面大小:

InnoDB Page SizeMaximum Tablespace Size
4KB16TB
8KB32TB
16KB64TB

参考1: Limits on Table Column Count and Row Size

image.png

参考2: Limits on Table Size

查看原文

赞 3 收藏 3 评论 0

认证与成就

  • 获得 56 次点赞
  • 获得 3 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 3 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

注册于 2016-08-07
个人主页被 693 人浏览