Fork me on GitHub

关于垃圾回收被误解的7件事

对Java垃圾回收最大的误解是什么?它实际又是什么样的呢?

当 我还是小孩的时候,父母常说如果你不好好学习,就只能去扫大街了。但他们不知道的是,清理垃圾实际上是很棒的一件事。可能这也是即使在Java的世界中, 同样有很多开发者对GC算法产生误解的原因——包括它们怎样工作、GC是如何影响程序运行和你能对它做些什么。因此我们找到了Java性能调优专家Haim Yadid,并把名为Java performance tuning guide的文章发表在Takipi的博客上。

最新博文:关于垃圾回收被误解的7件事
http://t.co/3QJLJuKCRqpic.twitter.com/aqQEF0zTkK
— Takipi (@takipid) April 6, 2015

带着对性能调优指南浓厚的兴趣,我们决定在这篇后续的博文中收集一些关于垃圾回收的流行观点,并且指出为什么它们完全是错误的。

来看看前7名:

1. 只有一个垃圾回收器

不,并且4也是错误的答案。HotSpot JVM一共有4个垃圾回收器:Serial, Parallel / Throughput. CMS, and the new kid on the block G1。别急,另外还有一些非标准的垃圾回收器和更大胆的实现,比如Shenandoah或 者其他JVM使用的回收器(C4——Azul开发的无停顿回收器)。HotSpot默认使用Parallel / Throughput回收器,但它常常不是你运行程序的最佳选择。比如CMS和G1会使GC停顿(GC pause)发生的频率降低,但是对于每次停顿所花费的时间,很可能比Parallel回收器更长。另一方面来说,在使用相同大小堆内存的情况下,Parallel回收器能带来更高的吞吐量。

结论:根据你的需求(可接受的GC停顿频率和持续时间)选择合适的垃圾回收器。

2. 并行(Parallel) = 并发(Concurrent)

一个GC周期(Garbage Collection cycle)可以以STW(Stop-The-World)的形式出现,这会发生一次GC停顿,也可以并发地执行从而无需暂停应用程序。更进一步来 讲,GC算法本身可以是串行的(单线程),也可以是并行的(多线程)。因此当我们提到并发的GC时,并不代表它是并行完成的,相反当提到串行GC时,也并 不意味着就一定会出现GC停顿。在GC的世界中,并发和并行是两个完全不同的概念。并发针对的是GC周期,而并行针对GC算法自身。

结论:垃圾回收的过程实际上有两步,启动GC周期和GC自身运行,这是不同的两件事。

阅读更多...

漫画:什么是协程?

img

img

————— 第二天 —————

img

img

img

img

img

————————————

img

img

img

img

img

img

什么是进程和线程

有一定基础的小伙伴们肯定都知道进程和线程。

进程是什么呢?

直白地讲,进程就是应用程序的启动实例。比如我们运行一个游戏,打开一个软件,就是开启了一个进程。

进程拥有代码和打开的文件资源、数据资源、独立的内存空间。

线程又是什么呢?

线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。

线程拥有自己的栈空间。

img

阅读更多...

G1垃圾回收器

原文 G1垃圾回收器 作者 xumingmingv

G1垃圾回收器其实是JDK7的特性,在目前JDK10都已经发布的情况下,已经不是什么新特性了,而我到它现在才关注它,可见我是有多么的懒;而我终于关注它了,可见我的懒还算是有救的 :)

G1其实是Garbage First的意思,垃圾优先? 不是,是优先处理那些垃圾多的内存块的意思。在大的理念上,它还是遵循JVM的内存分代假设(其实叫假设不准确,这是从实际Java应用的内存使用观察得到的结论):

90%的对象熬不过第一次垃圾回收,而老的对象(经历了好几次垃圾回收的对象)则有98%的概率会一直活下来。

基于这个分代假设,一般的垃圾回收器把内存分成三类: Eden(E), Suvivor(S)和Old(O), 其中Eden和Survivor都属于年轻代,Old属于老年代,新对象始终分配在Eden里面,熬过一次垃圾回收的对象就被移动到Survisor区了,经过数次垃圾回收之后还活着的对象会被移到Old区。

一般GC的内存分布

这样分代的好处是,把一个复杂的大问题,分成两类不同的小问题,针对不同的小问题,采用更有针对性的措施(分而治之):

  • 对于年轻代的对象,由于对象来的快去得快,垃圾收集会比较频繁,因此执行时间一定要短,效率要高,因此要采用执行时间短,执行时间的长短只取决于对象个数的垃圾回收算法。但是这类回收器往往会比较浪费内存,比如Copying GC,会浪费一半的内存,以空间换取了时间。
  • 对于老年代的对象,由于本身对象的个数不多,垃圾收集的次数不多,因此可以采用对内存使用比较高效的算法。

跟其它垃圾回收器不一样的是:G1虽然也把内存分成了这三大类,但是在G1里面这三大类不是泾渭分明的三大块内存,G1把内存划分成很多小块, 每个小块会被标记为E/S/O中的一个,可以前面一个是Eden后面一个就变成Survivor了。

这么做给G1带来了很大的好处,由于把三块内存变成了几百块内存,内存块的粒度变小了,从而可以垃圾回收工作更彻底的并行化。

G1的并行收集做得特别好,我们第一次听到并行收集应该是CMS(Concurrent Mark & Sweep)垃圾回收算法, 但是CMS的并行收集也只是在收集老年代能够起效,而在回收年轻代的时候CMS是要暂停整个应用的(Stop-the-world)。而G1整个收集全程几乎都是并行的,它回收的大致过程是这样的:

  • 在垃圾回收的最开始有一个短暂的时间段(Inital Mark)会停止应用
  • 然后应用继续运行,同时G1开始Concurrent Mark
  • 再次停止应用,来一个Final Mark
  • 最后根据Garbage First的原则,选择一些内存块进行回收。

由于它高度的并行化,因此它在应用停止时间(Stop-the-world)这个指标上比其它的GC算法都要好。

G1的另一个显著特点他能够让用户设置应用的暂停时间,为什么G1能做到这一点呢?也许你已经注意到了,G1回收的第4步,它是“选择一些内存块”,而不是整代内存来回收,这是G1跟其它GC非常不同的一点,其它GC每次回收都会回收整个Generation的内存(Eden, Old), 而回收内存所需的时间就取决于内存的大小,以及实际垃圾的多少,所以垃圾回收时间是不可控的;而G1每次并不会回收整代内存,到底回收多少内存就看用户配置的暂停时间,配置的时间短就少回收点,配置的时间长就多回收点,伸缩自如。

由于内存被分成了很多小块,又带来了另外好处,由于内存块比较小,进行内存压缩整理的代价都比较小,相比其它GC算法,可以有效的规避内存碎片的问题。

说了G1的这么多好处,也该说说G1的坏处了,如果应用的内存非常吃紧,对内存进行部分回收根本不够,始终要进行整个Heap的回收,那么G1要做的工作量就一点也不会比其它垃圾回收器少,而且因为本身算法复杂了一点,可能比其它回收器还要差。因此G1比较适合内存稍大一点的应用(一般来说至少4G以上),小内存的应用还是用传统的垃圾回收器比如CMS比较合适。

总结

G1通过在垃圾回收领域应用并行化的策略,把几块大内存块的回收问题,变成了几百块小内存的回收问题,使得回收算法可以高度并行化,同时也因为分成很多小块,使得垃圾回收的单位变成了小块内存,而不是整代内存,使得用户可能对回收时间进行配置,垃圾回收变得可以预期了。

分而治之、化整为零这些朴素的架构思想往往是很多牛叉技术产品背后的思想根源啊。

参考资料

MySQL数据库命名规范及约定

MySQL数据库命名规范及约定

一、【操作规范】

  1. 如无备注,则表中的第一个id字段一定是主键且为自动增长;

  2. 如无备注,则数值类型的字段请使用UNSIGNED属性;

  3. 如无备注,排序字段order_id在程序中默认使用降序排列;

  4. 如无备注,所有字段都设置NOT NULL,并设置默认值;

  5. 如无备注,所有的布尔值字段,如is_hot、is_deleted,都必须设置一个默认值,并设为0;

  6. 所有的数字类型字段,都必须设置一个默认值,并设为0;

  7. 针对varchar类型字段的程序处理,请验证用户输入,不要超出其预设的长度;

  8. 建表时将数据字典中的字段中文名和属性备注写入数据表的备注中(“PK、自动增长”不用写);

  9. 如无说明,建表时一律采用innodb引擎;

二、【常用表名约定】

  1. 说明:表前缀用项目名称首字母缩写;所以表名都小写,单词之间用下划线分开,单词都用单数形式

  2. user – 用户

  3. category – 分类

  4. goods – 商品、产品等一切可交易网站的物品都用此命名

  5. good_gallery – 物品的相册

  6. good_cate – 物品的分类,除了单独作为表名,其他地方分类单词一律用缩写cate

  7. attr – 属性

  8. article – 文章、新闻、帮助中心等以文章形式出现的,一般都用此命名

  9. cart – 购物车

  10. feedback – 用户反馈

  11. order – 订单

  12. site_nav – 包括页头和页尾导航

  13. site_config – 系统配置表

  14. admin – 后台用户 【RBAC标准表】

  15. role – 后台用户角色【RBAC标准表】

  16. access – 后台操作权限,相当于action【RBAC标准表】

  17. role_admin – 后台用户对应的角色【RBAC标准表】

  18. access_role – 后台角色对应的权限【RBAC标准表】

  19. 待续

阅读更多...

java中输出格式控制详解(System.out.printf用法)

除了System.out.print(ln),java中还有一种输出命令,而且比以上两种更为复杂、强大,那就是System.out.printf

样例:

1
2
3
4
5
6
7
8
9
10
11
public class Rentcar {

public static void main(String[] args) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 10; j++) {
System.out.printf("%5d", i*j);
}
System.out.println();
}
}
}

输出结果:

1
2
3
4
5
6
7
8
0    0    0    0    0    0    0    0    0    0
0 1 2 3 4 5 6 7 8 9
0 2 4 6 8 10 12 14 16 18
0 3 6 9 12 15 18 21 24 27
0 4 8 12 16 20 24 28 32 36
0 5 10 15 20 25 30 35 40 45
0 6 12 18 24 30 36 42 48 54
0 7 14 21 28 35 42 49 56 63

倘若不用System.out.printf ,而是用System.out.print(ln)格式就出现了明显错误,如下:

1
2
3
4
5
6
7
8
0000000000
0123456789
024681012141618
0369121518212427
04812162024283236
051015202530354045
061218243036424854
071421283542495663

好了,开始System.out.printf 详细学习吧

基本格式:格式控制符以一个%开始,一个字母结束,字母规定了方法按照何种方式打印这个值,例如d表示十进制整数(int),f表示浮点数(double).

例如:int x=12,y=10;

System.out.printf(“(%d,%d)”,x,y);

输出结果:

1
(12,10)

%d代替后面的参数,格式字符串中的格式控制字符的个数必须与后面提供的参数个数相匹配。

常用格式控制符

格式控制字符 结果
%d 整数
%8d 整数,右对齐,输出宽度为8
-6% 整数,左对齐,输出宽度为6
%f 浮点数
%8f 浮点数,右对齐,输出宽度为8
%.2f 浮点数,精确到百分位
%16.3f 浮点数,精确到千分位,输出到千分位,输出宽度为16

string同理,只是将d换成s.

Spring JPA 使用@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy 自动生成时间和修改者

转载地址 Spring JPA 使用@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy 自动生成时间和修改者

JPA Audit

在spring jpa中,支持在字段或者方法上进行注解@CreatedDate@CreatedBy@LastModifiedDate@LastModifiedBy,从字面意思可以很清楚的了解,这几个注解的用处。

@CreatedDate
表示该字段为创建时间时间字段,在这个实体被insert的时候,会设置值

@CreatedBy
表示该字段为创建人,在这个实体被insert的时候,会设置值

@LastModifiedDate@LastModifiedBy同理。

如何使用?

首先申明实体类,需要在类上加上注解@EntityListeners(AuditingEntityListener.class),其次在application启动类中加上注解EnableJpaAuditing,同时在需要的字段上加上@CreatedDate@CreatedBy@LastModifiedDate@LastModifiedBy等注解。

这个时候,在jpa.save方法被调用的时候,时间字段会自动设置并插入数据库,但是CreatedBy和LastModifiedBy并没有赋值,因为需要实现AuditorAware接口来返回你需要插入的值。

  • Application
1
2
3
4
5
6
7
8
9
10
11
12
13
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;


@SpringBootApplication
@EnableJpaAuditing
public class WalletApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(WalletApplication.class).web(true).run(args);
}
}
阅读更多...

MySQL命名、设计及使用规范

转载地址 MySQL命名、设计及使用规范

最近在看MySQL相关的内容,整理如下规范,作为一名刚刚学习MySQL的菜鸟,整理的内容非常的基础,中间可能涉及到有错误的地方,欢迎批评指正,看到有错误的地方期望看官留言。

数据库环境

  • dev:开发环境,开发可读写,可修改表结构。开发人员可以修改表结构,可以随意修改其中的数据但是需要保证不影响其他开发同事。
  • qa:测试环境,开发可读写,开发人员可以通过工具修改表结构。
  • sim:模拟环境,开发可读写,发起上线请求时,会先在这个环境上进行预执行,这个环境也可供部署上线演练或压力测试使用。
  • real:生产数据库从库(准实时同步),只读环境,不允许修改数据,不允许修改表结构,供线上问题查找,数据查询等使用。
  • online:线上环境,开发人员不允许直接在线上环境进行数据库操作,如果需要操作必须找DBA进行操作并进行相应记录,禁止进行压力测试。

这些环境的机器,一定要做到权限划分明确,读写帐号分离,并且有辨识度,能区分具体业务。例如用户名w_account,r_ account 分别代表读、写账号,account是读写账号。

命名规范

基本命名原则

  • 使用有意义的英文词汇,词汇中间以下划线分隔。(不要用拼音)
  • 只能使用英文字母,数字,下划线,并以英文字母开头。
  • 库、表、字段全部采用小写,不要使用驼峰式命名。
  • 避免用ORACLE、MySQL的保留字,如desc,关键字如index。
  • 命名禁止超过32个字符,须见名之意,建议使用名词不是动词
  • 数据库,数据表一律使用前缀
    • 临时库、表名必须以tmp为前缀,并以日期为后缀
    • 备份库、表必须以bak为前缀,并以日期为后缀
阅读更多...

面试题答案总结

如有错误欢迎指正

1.下面哪个函数是public void aMethod( ){…}的重载函数?

1
2
3
D

方法名称相同,参数列表不同,和返回类型无关

2.请问如何强制垃圾回收期立即回收一个对象?

1
2
3
4
5
6
7
8
D

垃圾(你家门口的垃圾)
虚拟机(环卫工人)
虚拟机(环卫工人)--- 会随即清除垃圾
你调用System.gc() = 告诉虚拟机(环卫工人)我这里有垃圾;
结果 他可能会马上过来 也可能会等他有空的时候再来 (不存在强制)
所以 调用System.gc() 等于告诉他 我这里有垃圾 仅此而已。

3.Java接口的修饰符可以为:

  • A. private
  • B. protected
  • C.final
  • D.abstract
1
2
3
4
5
6
7
8
9
10
D

在定义接口时,只要记住三点:
1.接口必须为public abstract,因为接口是高度抽象的类,它的存在就是被其他类实现。
2.接口中声明的变量必须为 public static final。
3.接口中定义的方法必须为public abstract,且没有方法体。当然java8新增“default”与static方法,可以方法实现
链接:https://www.nowcoder.com/questionTerminal/45910275c36f4b3fb9abdd00078d136e
来源:牛客网

接口 只能用 public 和 abstract 修饰。only public & abstract are permitted 。

4.以下所发正确的是()

  • A:Integer 继承 Number

  • B:Integer 是基本数据类型

  • C: Long a = new Long(30000)

    Long b = 30000
    

    ​ a == b

    ​ 返回true

  • D:String类可以被继承

1
2
3
4
5
6
7
8
A

B Integer不是基本数据类型
C Long a = new Long(3000);
Long b = 30000l;
a= b;
D 不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence

5.以下说法哪个是正确的()

1
2
3
4
5
6
7
8
9
B C

A volatile不能保证线程安全而synchronized可以保证线程安全。

volatile只能保证被其修饰变量的内存可见性,但如果对该变量执行的是非原子操作线程依旧是不安全的。

synchronized既可以保证其修饰范围内存可见性和操作的原子性,所以synchronized是线程安全的

D CopyOnWriteArrayList适合读多写少的情况
阅读更多...

Java 泛型,你了解类型擦除吗?

泛型,一个孤独的守门者。

大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。

文章开始的地方,先给大家奉上一道经典的测试题。

1
2
3
4
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();

System.out.println(l1.getClass() == l2.getClass());

请问,上面代码最终结果输出的是什么?不了解泛型的和很熟悉泛型的同学应该能够答出来,而对泛型有所了解,但是了解不深入的同学可能会答错。

正确答案是 true。

上面的代码中涉及到了泛型,而输出的结果缘由是类型擦除。先好好说说泛型。

泛型是什么?

泛型的英文是 generics,generic 的意思是通用,而翻译成中文,泛应该意为广泛,型是类型。所以泛型就是能广泛适用的类型。

但泛型还有一种较为准确的说法就是为了参数化类型,或者说可以将类型当作参数传递给一个类或者是方法。

那么,如何解释类型参数化呢?

1
2
3
4
5
6
7
8
9
10
11
12
public class Cache {
Object value;

public Object getValue() {
return value;
}

public void setValue(Object value) {
this.value = value;
}

}

假设 Cache 能够存取任何类型的值,于是,我们可以这样使用它。

阅读更多...

Mac IDEA 最常用快捷键

快捷键 描述
command + option + Space 智能提示
command + option + B 跳转至实现处
command + option + L 格式化代码
command + option + T 建立包围代码块try/catch if/else等
command + option + V 补全变量
command + option + ⬅️/➡️ 跳转到前/后面编辑处
command + shift + F 全局查找
command + shift + O 优化导包
command + shift + ⬆️/⬇️ 上/下移动代码
command + D 复制一行到下行
command + F 当前文件查找
command + H 显示层次结构
command + L 跳转到指定行
command + P 显示方法参数信息
command + X 选中全部
command + 1 打开Project视图
command + shift + ➕/➖ 展开/折叠所有代码
shift + shift 查找类
option + Enter 快捷修复
option + ⬆️/⬇️ 连续选中代码
control + ⬆️/⬇️ 方法间移动
  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信