学而时习之,不亦说乎?

Redis数据保存在内存中,服务器由于一些原因断电后会丢失数据,因此需要将数据保存在硬盘上,防止服务器断电后数据丢失。将数据保存在硬盘上的过程就叫做数据持久化。持久化方式可分为两种:将数据当前的状态进行保存,通过快照的方式,只保存数据;将数据操作的过程进行保存,只保存数据的操作过程;reids支持两种持久化操作,一种是RDB方式,一种是AOF操作方式。RDB方式会根据制定规则“定时”将数据保存在硬盘上。而AOF方式会在每次执行命令后将命令本身记录下来。

2016-10-25 0 评论 26 浏览
阅读全文

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

2019-11-30 0 评论 11 浏览
阅读全文
Java基础之线程池 有更新!

简介 线程池可以重用存在的线程,减少对象创建、消亡的开销,性能好。并且可以控制最大并发线程数,提高系统资源利用率,同时避免过多资源竞争,避免阻塞。 java.uitl.concurrent.ThreadPoolExecutor ThreadPoolExecutor提供了四个构造函数: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUni....

2019-02-23 0 评论 64 浏览
阅读全文

动态规划的本质是递归加缓存 解决动态规划的四个步骤: 设计暴力算法,找到冗余 设计并存储状态(一维,二维,三维数组,甚至用Map) 递归式(状态转移方程) 自底向上计算最优解(编程方式:把递归改为迭代) (递归是自顶向下,循环是自底向上) Leetcode198题 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。 示例 1: 输入: [1,2,3,1] 输出: 4 解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。 示例 2: 输入: [2,7,9,3,1] 输出: 12 解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。 偷窃到的最高金额 = 2 + 9 + 1 = 12 。 从题目中可以看出,....

2019-02-15 0 评论 43 浏览
阅读全文

单例模式是一次只创建一个实例,不允许多个存在。所以让类自身保存它的唯一实例。这个类保证没有其他实例可以被创建,并提供一个其他类访问的方法。先前在设计模式-单例模式中简单了介绍一下,现在开始填这个坑,比较几种单例模式的线程安全问题。 懒汉模式 懒汉模式就是在对象第一次使用时创建对象,下面这种方式,是非线程安全的,因为当多个线程同时判断成功instance == null,就会创建多个对象。 /** * @author Gavin * 懒汉模式,单例实例在第一次使用时创建对象 */ public class SingletonExample1 { //私有构造函数 private SingletonExample1() { } //单例对象 private static SingletonExample1 instance = null; //静态工厂方法 public static SingletonExample1 getInstance(){ if (instance == null) { instance = new SingletonExample1(); } return in....

2019-02-14 0 评论 46 浏览
阅读全文

简介 在Java运行过程中创建的对象,随着JVM的的停止,对象也会消失。为了将对象保存在本地硬盘或者是进行网络传输,需要将对象序列化,在需要的时候重新获取对象状态。Java为对象序列化和反序列化提供了两个接口: java.io.Serializable java.io.Externalizable 下面通过例子来演示两个接口的作用和区别。 Serializable 实现对象的序列化,必须实现Serializable接口。首先实现要序列化的对象: import java.io.Serializable; public class Student implements Serializable{ private static final long serialVersionUID = 1195127496667537096L; private String name; private int age; private String sex; private int id; public String getName() { return name; } public void setNa....

2019-02-14 0 评论 40 浏览
阅读全文

简介 程序计数器、虚拟机栈和本地方法栈的生存周期就是线程的生存周期,因此不需要考虑垃圾回收。Java中,GC的对象是堆空间和永久区。 怎么判断一个对象是否需要回收? 引用计数法 引用计数法就是给对象中添加一个引用计数器,当有对象引用时,计数器数值加1,引用失效时,计数器数值减1,当计数器数值为0,就通知GC回收对象。 图片中的B对象引用了D对象,如果B对象不再引用D对象,D对象的计数器数值就置为0,这样GC也会收回D对象。如果对象之间存在循环引用,就会出现无法回收的对象。如下图所示: 图中BCD循环引用,根对象已经不引用B对象,也就是说BCD对象应该被GC,但因为BCD计数器数值都不为0,因此引用计数法无法通知GC来回收对象。就是存在这种问题,Java虚拟机中没有选用引用计数法来判断对象是否存活。 可达性分析算法 在Java和C#等主流商用程序语言中,都是使用可达性分析算法来判断对象是否存活。算法思路是从一系列的“GC Roots”的对象最为起始点,从这些节点向下搜索,走过的路径成为引用链,当一个对象到GC Roots没有任何引用链相连,就说明此对象不可用。如下图所示: 设A为根....

2019-02-12 0 评论 133 浏览
阅读全文

介绍 Java为每种基本数据类型提供了对应的包装类型,比如int对应的包装类型是Integer,创建一个Integer对象需要使用new关键字,在JDK5之后提供了自动装箱拆箱,可以自动将基本数据类型直接转换为包装类型,也可以直接将包装类型自动转成基本数据类型,这就叫做自动装箱拆箱。 Integer i = 100; //自动装箱 int j = i; //自动拆箱 Integer中的实现 Integer自动装箱拆箱是基于valueOf()和intValue方法实现。当我们执行 Integer i = 100; 其实就是执行了: Integer i = Integer.valueOf(100); 当执行: int j = i; 就是执行了: int j = i.intValue(); valueOf() 这是valueOf的实现代码: public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerC....

2019-02-10 0 评论 29 浏览
阅读全文

介绍 String类是final修饰,说明不可以被继承,String一旦被创建就不能改变,对String修改就会创建一个新的字符串,因此禁止使用循环修改字符串。 Sring在内存中的位置 String str1 = new String("hello"); String str2 = new String("hello"); String str3 = "hello"; String str4 = "hello"; String str5 = "he"+"llo"; String str6 = "he"; String str7 = "llo"; System.out.println(str1==str2); //false System.out.println(str1==str3); //false System.out.println(str3==str4); //true System.out.println(str4 == str5); //true System.out.println(str3=="hello"); //true System.out.println(s....

2019-02-07 0 评论 97 浏览
阅读全文

内存分代策略 简介 HotSpot中为了提高内存对象内存分配和垃圾回收的效率,将内存分为了新生代(Eden+From Survivor+To Survivor)、老年代(OldGen)和永久代(PermGen)。新创建的对象分配在新生代,多次回收还存活的对象放在老年代,类信息、静态变量和字符串常量等存放在永久代中。新生代中需要频繁执行垃圾回收,老年代中不需要频繁垃圾回收,永久代一般来说不实现垃圾回收。这样对不同的区域实行不同的垃圾回收算法,可以提高垃圾回收效率。 在Java7之前,方法区在永久代,永久代和堆隔离,使用的是堆空间,永久代大小在启动JVM时设置一个固定的值,不可变;Java7中将static从永久代移到堆中;Java8中取消永久代,使用元空间(Metaspace)替代,与堆共享物理内存,逻辑上可以认为和堆在一起。元空间使用的是系统内存,因此有足够空间。 新生代 新生代垃圾回收效率高,Minor GC是新生代的GC,回收速度快,Eden空间不足时会触发Minor GC进行回收操作。新生代分为三块空间,一个Eden和两个Survivor(通常称为To Survivor和Fro....

2019-01-30 0 评论 85 浏览
阅读全文

注解 什么是注解 注解也叫Annotation,从JDK5.0开始引入。 Annotation不是程序,但是可以对程序作出解释 可以被其他程序读取 内置注解 @Override 定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。 @Override public String toString (){ return ""; } 在阿里巴巴Java开发手册中强制要求所有重写方法必须加@Override,防止重写方法名称写错。 @Deprecated 定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类,表示不建议使用这样的元素,通常被遗弃。 @SuppressWarnings 定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。 自定义注解 先了解一下元注解: 元注解的作用就是负责注解其他注解。 Java定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。这些类型和它们所支持的类在java.lan....

2019-01-29 0 评论 31 浏览
阅读全文

简介 Object类在java.lang包中,是所有类的父类,所有类都间接或者直接继承Object类。Object类中主要有registerNatives()、getClass()、hashCode()、equals()、clone()、toString()、notify()、notifyAll()、wait()和finalize()等方法。其中 getClass()、notify()、notifyAll()和wait()等方法使用final关键字修饰,因此子类不能覆盖。 源代码 registerNatives()方法 private static native void registerNatives(); //在类加载时就执行这个方法 static { registerNatives(); } registerNatives()方法是注册一些本地方法,具体实现在本地的代码中,所以我也不清楚里面干了什么。学Java还是有必要学习一下JNI的,等我找到工作要好好研究一下。 在Java中,静态代码的调用顺序:父类静态-->子类静态-->父类非静态-->父类构造--&....

2019-01-28 0 评论 96 浏览
阅读全文

介绍 HashMap是基于哈希表的Map接口的实现,并允许使用 null 值和 null 键。HashMap在JDK1.8之前使用的是哈希表+链表的方式存储数据。在JDK1.8之后,如果链表过长则将链表转成红黑树。  源码分析 继承 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {} HashMap继承了AbstractMap及实现了Map、Cloneable和Serializable接口。 成员变量 private static final long serialVersionUID = 362498820763181265L; // aka 16 默认的初始容量 12222 = 16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //最大容量是2的30次方 static final int MAXIMUM_CAPA....

2019-01-26 0 评论 88 浏览
阅读全文

  我的博客, 经过了几次迁移,一开始在简书上发表,然后移到码云上,再到github,现在又将网站迁移至华为云的服务器,这是第一次使用solo发博客,纪念一下。 迁移   记不清楚是大一还是大二,学长告诉我简书特别好用,我开始尝试使用简书,那时候的简书特别的简洁,用起来特别的顺手。   后来看到别人都有属于自己的博客,特别的心动,2016年的时候,我觉得把网站放在服务器上花费的代价太大,就打算放在github上。于是我搭建了基于HEXO博客框架的博客,申请了一个我比较喜欢的域名:gwt.science;虽然.science的后缀有点长,比较便宜,我续费了十年,现在看来还是比较坑的,因为没有办法备案。一开始博客我是放在码云上的,放在码云上国内访问的速度比较快,并且百度还能收录,百度也收录了几条,那时候不备案还能访问。后来码云强制加了一个进博客之前的广告页,进博客感觉特别不舒服,我又将博客移到了github上。这种放在github上的网站,优点是免费,但是缺点也很多,最大的缺点我认为是没有评论功能,使用第三方评论功能,要么是被墙,....

2019-01-24 0 评论 246 浏览
阅读全文

介绍 Stack是一种先进后出的数据结构,继承于Vector,所以Stack是通过数组实现。 源码分析 继承 public class Stack<E> extends Vector<E> {} 构造函数 Stack只有一个默认的构造函数,创建一个空的栈。 public Stack() { } 所有API boolean empty() synchronized E peek() synchronized E pop() E push(E object) synchronized int search(Object o) Stack只是在Vector的基础上添加了几个方法。 //push 将数据存放在数组的最后 public E push(E item) { addElement(item); return item; } //弹出数据操作 public synchronized E pop() { E obj; int len = size(); //先获取栈的大小 obj = peek(); //取出来栈中最上面的数据,也就是数组中最后一个数....

2019-01-18 0 评论 30 浏览
阅读全文

介绍 Vector和ArrayList一样,内部都是通过数组实现。Vector是线程安全的,但是由于使用了synchronized方法,性能上比ArrayList差。 源码分析 继承 public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {} Vector继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。 成员变量 protected Object[] elementData; //存放数据的对象数组 protected int elementCount; //记录存了多少个元素 protected int capacityIncrement; //当向量溢出时增加的数量 private static final long serialVersionUID = -2767605614048989439L; 构造函数 //....

2019-01-05 0 评论 47 浏览
阅读全文

对象创建 对象创建过程 虚拟机遇到new指令,先去检查这个指令的参数是否在常量池中定位到一个类的符号引用并检查这个符号引用的类是否已经被加载、解析和初始化过。 检查常量池中是否有将要创建对象所属类的符号引用 常量池中没有类的符号引用,说明这个类还未定义,报ClassNotFoundException; 检查这个符号引用的类是否已经被JVM加载 类未加载,找打类的class文件,加载到方法区; 类已经被JVM加载,则准备为对象分配内存 对象所需的内存大小在类加载完成后便完全确定(类的所有对象的内存大小相同),把一块确定大小的内存在Java堆中划分出来。 内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零(不包括对象头)。 设置对象头中的信息 完成创建,可以调用对象的构造函数初始化。 分配内存的两种方式 用哪种方式由Java堆是否完整和gc收集器决定 指针碰撞。(如果内存是规整的,用过的内存在一边,空闲的内存在另一边,中间放着一个指针作为分界点的指示器,分配内存就是将指针向空闲区域移动一段与对象相同的距离。) 空闲列表,(已使用的内存和空闲的内存相互交错,虚拟机必须....

2018-12-31 0 评论 28 浏览
阅读全文

通过show status 了解SQL执行频率 mysql> show status like 'Com_%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Com_admin_commands | 0 | | Com_alter_db | 0 | | Com_alter_db_upgrade | 0 | | Com_alter_event | 0 | | Com_alter_function | 0 | | Com_alter_procedure | 0 | | Com_alter_server | 0 | | Com_alter_table | 0 | | Com_alter_tablespace | 0 | | Com_analyze | 0 | | Com_assign_to_keycache | 0 | | Com_begin | 0 | | Com_binlog | 0 | | Com_call_pr....

2018-12-30 0 评论 43 浏览
阅读全文

简介 Java虚拟机管理的内存包括下面五个运行时数据区域: 程序计数器 Java虚拟机栈 本地方法栈 堆 方法区 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,可以看做当前所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,也就是下一条字节码指令的地址。 线程私有(多线程并发执行时每个线程必须有自己的程序计数器,用来记录自己执行字节码的位置,方便CPU时间片轮询切换后继续执行)。 如果执行的是Native方法(指本地方法:一般使用C/C++在另外文件中编写),这个计数器值记为空。 此区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域(程序计数器存放当前线程下一条指令所在的位置,可以预见其大小,所以不会内存溢出)。 Java虚拟机栈 Java虚拟机栈是线程私有,生命周期与线程相同。 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量表、操作数栈、动态链接、方法出口等) JVM为每个线程创建一个栈,用于存放该线程....

2018-12-29 0 评论 24 浏览
阅读全文