List 中的相同数据进行分组
要求同一组数据分组需求:一个 list 里可能会有出现一个用户多条数据的情况。要把多条用户数据合并成一条。
思路思路:将相同的数据中可以进行确认是相同的数据,拿来做分组的 key,这样保证不会重。实际中使用,以用户数据为例,可能用户名和身份证号是不会变的,用这两个条件拼接起来。
12345678910111213141516171819202122232425262728293031public class TestSort { public static void main(String[] args) { List<User> users = Arrays.asList( new User(1, "liu big big", "123456789"), new User(2, "liu big big", "987654321"), new User(3, &qu ...
java 程序驻留不退出保持运行
前言不管是C、java、go 程序,要让程序一直不间断动行,就肯定需要保持线程不退出,才能可能持续运行。
今天说的是java,一般来说从main方法开始运行结束之后,线程也就退出,如何保证线程不退出?实际上只要证保有一个线程在持续运行,程序就不算退出。一般来说只需要保持main线程不退出,然后其他线程不间断的工作就OK。实际上在如果开启多个线程,就算主线程执行结束了,子线程没有结整,JVM一样不会退出。
保持运行上面说了,思路都量样的,就是阻塞一条线程,让JVM不要退出,一般是阻塞主线程main,让他阻塞不退出,直到需要退出的时候再限出。演示几种不退出的方式:
读取流: System.in.read();
等待锁:
wait()
CountDownLatch(1).await();
死循环: while(true)
睡眠: sleep()
这几种方式,不是阻塞,就是睡眠,大概思路都差不多,就是
读取流通过阻塞主线程,来验证一下,运行后就可以看到service的run方法执行完后,程序也不会退的。代码可以自行复制验证。这种方式可以用,一般线上服务都是通过kill -15来退出应用 ...
JVM 分代的概念
堆,才有分代的概念。堆,才有分代的概念。堆,才有分代的概念。
分代JVM 将内存分为大致分为三个区域,1.8 前后有区别
为什么要分代
不分代行不行
不分代完全可以,但是分代的唯一理由是为了优化GC性能。怎么优化?如果不进行分代,每次GC都要把整片堆扫一遍来寻找垃圾对象,太慢。分代直接把对象创建到某一个分代区,这样GC就可以针对这一分代区域就行优化,就不费劲了。
年轻代
eden、survivor、from、to
年轻代分三个部分:
Eden 区,即新生对象区,除大对象以外,新生对象都创建在这里。
Survivor 区,即幸存区,该区域又分两个空间s0 和 s1 分别也叫 from 和 to,默认比例8:1。
对象经历的过程
新创建对象,分配到Eden区,除大对象特殊处理。
在 Eden 区经过一次GC后,如果仍存活,移到 Survivor。
在 Survivor 中又经历一次 GC,年龄会增加一岁。
年龄到一定程度,移到老年代。
年轻代使用什么GC算法
是复制算法。
为什么选复制算法?因为:年轻代中的80%以上的对象很快就死亡。所以,在年轻代的垃圾回收算法使用 ...
linux-内核版本说明
说明最近查看 Linux core 的版本,发现这个版本号有点复杂,稍微查了一下。
例如:
2.6.18-92.el5
这里以点.作为分格符,分别是:
主版本.次版本.释出版本-修改版本
1.主、次版本为奇数:发展中版本(development)如 2.5.xx,这种核心版本主要用在测试与发展新功能,所以通常这种版本仅有核心开发工程师会使用。 如果有新增的核心程序代码,会加到这种版本当中,等到众多工程师测试没问题后,才加入下一版的稳定核心中;
2.主、次版本为偶数:稳定版本(stable)如 2.6.xx,等到核心功能发展成熟后会加到这类的版本中,主要用在一般家庭计算机以及企业版本中。 重点在于提供使用者一个相对稳定的 Linux 作业环境平台。
相关链接https://www.kernel.org/
wait-notify 实现生产者消费者模式
wait 和 nofity 在线程中的搭配使用,其实就是生产者消费者的一种应用。
一、为什么要有生产者消费者模式在实际应使用多线程时,线程间的角色并不一完全一样的,有的线程负责生产数据,有的线程负责消费数据。所在就会有一种情况,就是: 生产者生产数据太快,消费者消费能力跟不上。
比较线程A 不断的new 对象,并将对象放到一个队列里,而线程B,不断的从队列里拿出数据进行逻辑操作。显然线程A new 对象这一操作会更快,如果一直持续下去内存有可能会被撑暴。
解决这个问题的思路之一就是:生产者-消费者模式
二、wait、notify 简单应用示例Wait 类12345678910111213141516171819202122232425262728293031323334public class SimpleWaitTest implements Runnable { private Object object; public SimpleWaitTest(Object object) { this.object = object; ...
java 序列化使用
简述开始前先搞清楚一个问题什么是序列化?就是一个目的:将 JAVA 对象转换成二进制的数据进行各种操作,如传输、保存、增删等。是的,你没看错,就是要转成二进制的数据。
主要聊三个问题:Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?
还是一样,先说怎么用,再说为什么。
使用这次的示例是准备了几种场景:
序列化后文件存储
序列化后内存中使用
java当中提供了原生序列化方式,也就是把内存中的数据,转换成二进制,或者把二进制数据,转换成内存数据的API。在java的世界中,二进制数据称为流,通过流,也就是抽象成一个个流对象进行处理。
序列化并持久化首先第一步,需要实现序列化接口,才能被序列化。
123456789101112public class TestObj2 implements Serializable { private String name; public String getName() { return name; } public void setName(String na ...
algorithm--数组分批次算法
要求对一个数组,按指写个数n,划为一组。比如有一个数组,包含1200000 的数据,要求每1000为一组。放到一个新的Array里要怎么处理呢。方法肯定有很多,可以一一来验证。
取模可能是最简单的方式:取模。可以用少最数据验证一下。思路很简单:
对 step 取模,每到1000就打印一下,这一步也机以创建新的数组都可以的
else就是普通的处理
123456789101112131415161718public class Test { public static void main(String[] args) { int total = 120; int step = 10; int[] array = new int[total]; for (int i = 0; i < total; i++) { if (i % step == 0) { // 在这里相当于可以做一些特殊的开头处理,比如创建一个新的容器之类,这里我就直接用来打印 array[i] = i; ...
shell 实现一个下载脚本
前言在写复杂脚本时,往往需要复用下载这个操作,刚好碰到这个问题,就把下载功能抽成一个函数,拿来复用。
实现实现就比较简单了,直接上代码,这段代码复制就可以直接使用。功能上判断一下当前系统中使用的的wget还是curl,选择其中一个工具进行下载。
12345678910111213141516171819202122#!/bin/bashdownload() { local url=$1 local file_name=$2 if type wget >/dev/null 2>&1; then wget --no-check-certificate -q $url elif type curl >/dev/null 2>&1; then echo "curl -OLJ $url" curl -OLJ $url else echo 'info: no exists wget or curl, make sure the system can use the "wget ...
内存不足 java应用无法启动
原因在启动应用时,发现应用一启动就挂掉,线程号一闪就没了,有点奇怪,查看一下错误日志。报了一个错: Invalid initial heap size: -Xms9g
完整日志如下
123456789Thu May 19 18:14:59 CST 2016Invalid initial heap size: -Xms9gThe specified size exceeds the maximum representable size.Error: Could not create the Java Virtual Machine.Error: A fatal exception has occurred. Program will exit.[java-tron@chaindev010 FullNodeHelloMessage]$ java -versionjava version "1.8.0_161"Java(TM) SE Runtime Environment (build 1.8.0_161-b12)Java HotSpot(TM) 64-Bit Serve ...
jvm 的局部变量表
局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。Java中方法的局部变量是放在虚拟机栈的局部变量表里面,形参也算一个。本地变量表,就是局部变量表,只是翻译不同。代码说明
运行时栈帧中存储了以下内容
局部变量
操作数栈
动态链接
返回地址
附加信息
每一个方法的调用开始和结束都是栈的压入(入栈)和弹出(出栈)的过程
12345public static void main(String[] args) { byte[] waste = new byte[6 * 1024 * 1024]; int new_var = 0; System.gc(); }
反编译得到:
1234567891011public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=1 0: ldc #2 ...