- 博客(199)
- 收藏
- 关注
原创 Java应用中使用ShutdownHook友好地清理现场
在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码。Java中得ShutdownHook提供了比较好的方案。JDK在1.3之后提供了Java Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:1)程序正常退出2)使用System.exit()3)终端使用Ctrl+C触发的中断4)系统关闭5)使用Kill pid命令干掉进程注:在使
2021-02-03 17:18:52
100
原创 Java finally语句到底是在return之前还是之后执行?
网上有很多人探讨Java中异常捕获机制try…catch…finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语句是不会被执行的:(1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。(2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟
2021-02-02 23:07:22
109
原创 Java线程原语弃用
为什么是线程停止不赞成?因为它本质上是不安全的。停止线程会使其解锁其锁定的所有监视器。(当ThreadDeath异常在堆栈上传播时,监视器将被解锁。)如果以前受这些监视器保护的任何对象处于不一致状态,其他线程现在可能会以不一致的状态查看这些对象。据说这些物品被损坏了。当线程对损坏的对象进行操作时,可能会导致任意行为。这种行为可能是微妙的,很难被发现,也可能是被宣布的。与其他未经检查的异常不同,ThreadDeath无声地杀死线程;因此,用户没有警告他的程序可能已损坏。腐败在实际损害发生后的任何时候都会显现
2021-02-02 22:42:10
150
原创 Java跳出多重循环的方法
我们一般用break和cuntinue来控制单个循环,但是如果遇到有多个循环的情况呢,比如下面这个:for (int i=0; i<10; i++) { for (int j=0; j<10; j++) { for (int k=0; k<10; k++) { } } }如果有以下需求一般怎么做呢?(1)当j
2021-01-31 23:05:14
941
原创 Java进阶 消息中间件架构体系 — ActiveMQ研究
一、前言MQ全称为Message Queue,即消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。开发中消息队列通常有如下应用场景:1、任务异步处理。将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。2、应用程序解耦合MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。市场上还有哪些消息队列?ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ、Redis。我们
2021-01-31 22:56:08
427
原创 Java Socket编程基础及深入讲解
一、Socket通信基本示例这种模式是基础,必须掌握,后期对Socket的优化都是在这个基础上的,也是为以后学习NIO做铺垫。package yiwangzhibujian.onlysend;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;public class SocketServer { public static void main(String[] args) thro
2021-01-30 23:14:31
350
原创 【Java并发】Thread及ThreadGroup杂谈
一、前言最近开始学习Java并发编程,把学习过程记录下。估计不是那么系统,主要应该是Java API的介绍(不涉及最基础的概念介绍),想要深入系统学习推荐看一本书《Java Concurrency in Practice 》(建议看英文,也可以看中文译本:《 Java 并发编程实战》)。并发编程的基础就是线程,所以这一篇对线程做初步了解。二、Thread和ThredGroup的关系因为Thread的构造函数中有关于ThradGroup的,所以了解它们之间的关系是有必要的。ThradGroup之间的关
2021-01-30 22:52:07
247
原创 【Java 并发】详解 ThreadPoolExecutor
前言线程池是并发中一项常用的优化方法,通过对线程复用,减少线程的创建,降低资源消耗,提高程序响应速度。在 Java 中我们一般通过 Exectuors 提供的工厂方法来创建线程池,但是线程池的最终实现类是 ThreadPoolExecutor,下面我们详细分析一下 ThreadPoolExecutor 的实现。基本使用我们首先看下线程池的基本使用。在下面的代码中我们创建一个固定大小的线程池,该线程池中最多包含 5 个线程,当任务数量超过线程的数量时,就将任务添加到任务队列,等线程空闲之后再从任务队列中
2021-01-30 22:24:23
204
原创 【Java并发】详解 AbstractQueuedSynchronizer
前言队列同步器 AbstractQueuedSynchronizer(以下简称 AQS),是用来构建锁或者其他同步组件的基础框架。它使用一个 int 成员变量来表示同步状态,通过 CAS 操作对同步状态进行修改,确保状态的改变是安全的。通过内置的 FIFO (First In First Out)队列来完成资源获取线程的排队工作。更多关于 Java 多线程的文章可以转到 这里AQS 和 synchronized在介绍 AQS 的使用之前,需要首先说明一点,AQS 同步和 synchronized 关键
2021-01-29 23:04:21
321
原创 Java 魔法类: sun.misc.Unsafe详细讲解
Java是一门安全的编程语言,防止程序员犯很多愚蠢的错误,它们大部分是基于内存管理的。但是,有一种方式可以有意的执行一些不安全、容易犯错的操作,那就是使用Unsafe类。本文是sun.misc.Unsafe公共API的简要概述,及其一些有趣的用法。Unsafe 实例在使用Unsafe之前,我们需要创建Unsafe对象的实例。这并不像Unsafe unsafe = new Unsafe()这么简单,因为Unsafe的构造器是私有的。它也有一个静态的getUnsafe()方法,但如果你直接调用Unsafe
2021-01-29 22:50:10
1148
原创 Java集合:整体结构
一、Java中集合Java中集合类是Java编程中使用最频繁、最方便的类。集合类作为容器类可以存储任何类型的数据,当然也可以结合泛型存储指定的类型(不过泛型仅仅在编译期有效,运行时是会被擦除的)。集合类中存储的仅仅是对象的引用,并不存储对象本身。集合类的容量可以在运行期间进行动态扩展,并且还提供很多很方便的方法,如求集合的并集、交集等。二、集合类结构Java中的集合包含多种数据结构,如链表、队列、哈希表等。从类的继承结构来说,可以分为两大类,一类是继承自Collection接口,这类集合包含List、
2021-01-28 23:11:54
116
原创 Java 并发编程:volatile的使用及其原理
一、volatile的作用在《Java并发编程:核心理论》一文中,我们已经提到过可见性、有序性及原子性问题,通常情况下我们可以通过Synchronized关键字来解决这些个问题,不过如果对Synchronized原理有了解的话,应该知道Synchronized是一个比较重量级的操作,对系统的性能有比较大的影响,所以,如果有其他解决方案,我们通常都避免使用Synchronized来解决问题。而volatile关键字就是Java中提供的另一种解决可见性和有序性问题的方案。对于原子性,需要强调一点,也是大家容易
2021-01-28 23:01:15
118
原创 【Java 并发】详解 ThreadLocal
前言ThreadLocal 主要用来提供线程局部变量,也就是变量只对当前线程可见,本文主要记录一下对于 ThreadLocal 的理解。更多关于 Java 多线程的文章可以转到 这里。线程局部变量在多线程环境下,之所以会有并发问题,就是因为不同的线程会同时访问同一个共享变量,例如下面的形式public class MultiThreadDemo { public static class Number { private int value = 0; pu
2021-01-28 22:37:31
179
原创 深入分析 ThreadLocal 内存泄漏问题
前言ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。但是如果滥用 ThreadLocal,就可能会导致内存泄漏。下面,我们将围绕三个方面来分析 ThreadLocal 内存泄漏的问题ThreadLocal 实现原理ThreadLocal为什么会内存泄漏ThreadLocal 最佳实践ThreadLocal 实现原理ThreadLocal的实现是这样的:每个Thread 维护一个 Thre
2021-01-28 22:25:26
176
原创 Java 理论与实践 — 用弱引用堵住内存泄漏
要让垃圾收集(GC)回收程序不再使用的对象,对象的逻辑 生命周期(应用程序使用它的时间)和对该对象拥有的引用的实际 生命周期必须是相同的。在大多数时候,好的软件工程技术保证这是自动实现的,不用我们对对象生命周期问题花费过多心思。但是偶尔我们会创建一个引用,它在内存中包含对象的时间比我们预期的要长得多,这种情况称为无意识的对象保留(unintentional object retention)。全局 Map 造成的内存泄漏无意识对象保留最常见的原因是使用 Map 将元数据与临时对象(transient o
2021-01-28 22:04:33
281
原创 Java设计模式之单例模式
Java中单例模式是一种常见的模式,单例模式分为三种:懒汉式单例、恶汉式单例、登记式单例。单例模式有一下特点:.单例类只能有一个实例.单例类必须自己创建自己的唯一实例.单例类必须给所有其他对象提供这一实例单例模式必须确保只有一个实例,而且自行实例化并向系统提供这个实例。选择单例模式就是为了避免不一致状态。一、懒汉式单例package com.singleton;public class Singleton { //懒汉式单例,在第一次调用时实例化自己 private S
2021-01-27 23:12:37
127
1
原创 java深度搜索与广度优先搜索
图结构展示:实现过程:首先,我们来看看图结构在代码中的实现。有三块逻辑:1.图中的节点:[java] view plain copyprint?public class GraphNode { public List<GraphEdge> edgeList = null; private String label = ""; public GraphNode(String label) { this
2021-01-27 23:04:52
298
原创 JavaScript单元测试框架JsUnit基本介绍和使用
XUnit frameworkXUnit是一套标准化的独立于语言的概念和结构集合,用于编写和运行单元测试(Unit tests).每一个语言都有一个用于单元测试的XUnit框架,比如Java有JUnit, C++有CppUnit, PHP有PHPUnit, Oracle SQL有UTPL/SQL.JsUnit遵循XUnit的一些惯例:单元测试在JsUnit中叫做Test Functions.est Functions所在的HTML页面叫做Test Page.一个Test Page是一个包含js
2021-01-27 22:56:30
1031
原创 Java虚拟机 — 类文件结构
我们知道计算机是由晶体管、电路板等组装而成的电子设备,而这些电子设备其实只能识别0与1的信号。那么问题来了,我们在操作系统上编写的Java代码(由字母、数字等各种符号组成),打包后部署到服务器上,是如何被计算机所识别并运行的呢?另外,操作系统有很多种,包括Windows系统,Linux系统,Mac OS系统等,而我们同样的Java代码,却可以不做任何处理在不同的系统上正常运行,这又是为啥呢?带着这些疑问,你将会在下面的介绍中得到答案!!!1、Java虚拟机的两个特性①、语言无关性对于Java语言,
2021-01-27 22:35:17
200
原创 【Java】数组不能通过toString方法转为字符串
java里,所有的类,不管是java库里面的类,或者是你自己创建的类,全部是从object这个类继承的。object里有一个方法就是toString(),那么所有的类创建的时候,都有一个toString的方法。这个方法是干什么的呢?首先我们得了解,java输出用的函数print();是不接受对象直接输出的,只接受字符串或者数字之类的输出。那么你想把一个创建好的对象拿来输出怎么办?例如:package com.spring.h3;public class Test2 { public sta
2021-01-27 22:05:49
258
原创 javaweb之Java过滤器与包装设计模式的实用案例
在filter中可以得到代表用户请求和响应的request、response对象,因此在编程中可以使用Decorator(装饰器)模式对request、response对象进行包装,再把包装对象传给目标资源,从而实现一些特殊需求。一、Decorator设计模式1.1、Decorator设计模式介绍当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强:编写子类,覆盖需增强的方法。使用Decorator设计模式对方法进行增强。在阎宏博士的《JAVA与模式》一书中开头是这样描述装饰(
2021-01-26 22:31:04
224
原创 javaweb—Apache的DBUtils框架
一、commons-dbutils简介commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。commons-dbutilsAPI介绍:org.apache.commons.dbutils.QueryRunnerorg.apache.commons.dbutils.ResultSetH
2021-01-26 22:11:29
140
原创 Java中常见数据结构Map之HashMap
一:JDK7中的HashMap:HashMap底层维护一个数组table, 数组中的每一项是一个key,value形式的Entry。我们往HashMap中所放置的对象实际是存储在该数组中。Map中的key,value则以Entry的形式存放在数组中。这个Entry应该放在数组的哪一个位置上, 是通过key的hashCode来计算的。这个位置也成为hash桶。通过hash计算出来的值将通过indexFor方法找到它所在的table下标:这个方法其实是对table.length取模, 当两个
2021-01-26 21:57:06
341
原创 通过反编译深入理解Java String及intern
一、字符串问题字符串在我们平时的编码工作中其实用的非常多,并且用起来也比较简单,所以很少有人对其做特别深入的研究。倒是面试或者笔试的时候,往往会涉及比较深入和难度大一点的问题。我在招聘的时候也偶尔会问应聘者相关的问题,倒不是说一定要回答的特别正确和深入,通常问这些问题的目的有两个,第一是考察对 JAVA 基础知识的了解程度,第二是考察应聘者对技术的态度。我们看看以下程序会输出什么结果?如果你能正确的回答每一道题,并且清楚其原因,那本文对你就没什么太大的意义。如果回答不正确或者不是很清楚其原理,那就仔细看
2021-01-26 21:39:19
117
原创 Java8内存模型—永久代(PermGen)和元空间(Metaspace)
一、JVM 内存模型根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。1、虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建。栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用)、操作数栈、方法出口等信息。栈的大小可以固定也可以动态扩展。当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误,不过这个深度范围不是一个恒定的值,我们通过下面这段程序可以测试一下这个结果:
2021-01-26 21:29:13
196
原创 Java中Vector和ArrayList的区别
首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList、Vector和LinkedList。List用于存放多个元素,能够维护元素的次序,并且允许元素的重复。3个具体实现类的相关区别如下:1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制
2021-01-25 23:30:30
452
原创 Java之反转字符串和相关字符编码问题
反转字符串一直被当作是简单问题,大家的思想主要就是利用遍历,首尾交换字符实现字符串的反转。例如下面的代码,就可以简单实现反转。 1 public String reverse(char[] value){ 2 for (int i = (value.length - 1) >> 1; i >= 0; i--){ 3 char temp = value[i]; 4 value[i] = value[value.length -
2021-01-25 23:22:23
116
原创 Java 并发编程:核心理论
并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能。它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰、思维缜密,这样才能写出高效、安全、可靠的多线程并发程序。本系列会从线程间协调的方式(wait、notify、notifyAll)、Synchronized及Volatile的本质入手,详细解释JDK为我们提供的每种并发工具和底层实现机制。在此基础上,我们会进一步分析java.util.concurrent包的工具类,包括其使用方式、实现源码及其背后的原理。本文是该系列的
2021-01-25 23:07:26
73
原创 JAVA数据结构之线性表
线性表是其组成元素间具有线性关系的一种数据结构,对线性表的基本操作主要有,获取元素,设置元素值,遍历,插入,删除,查找,替换,排序等。而线性表可以采用顺序储存结构和链式储存结构,本节主要讲解顺序表、单链表以及双链表的各种基本操作。1:线性表抽象的数据类型线性表:是由n(n>=0)个数据相同的元素组成的有限序列。线性表的定义接口如下public interface IList<T> { /** * 是否为空 * @return */ boo
2021-01-25 22:30:57
270
原创 JAVA - 构造函数的继承
1、子类中无参构造函数,可直接继承父类中无参构造函数,前提是所有变量均为public如下:父类Student中有空构造函数Student(),子类Pupil中有空构造函数Pupil(),后者会继承前者。注:在本例中,父类中的name、height都是public的,如果是private就无法直接继承。package javastudy;public class ConfunDemo5 { public static void main(String[] args) { P
2021-01-25 13:59:42
1133
原创 JAVA数组的遍历和取最值
1、获取数组中的所有元素,会用到数组的遍历数组的遍历,通常用for循环。public class ArrayDemo { public static void main(String[] args) { int[] arr = new int[3]; for(int i=0;i<arr.length;i++) //数组名.length即数组的长度。数组的角标最小值是0,最大值是length-1。 { S
2021-01-23 23:15:23
592
原创 静态代码块的执行方式和顺序
1、静态代码块格式:static{ 执行语句}特点:随着类的加载而执行,且只执行一次,并优先于主函数。用于给类初始化的。2、执行顺序:示例一静态代码块随着类加载而加载有多个静态代码块的,按代码块前后顺序加载一个代码块,只执行一次。package javastudy;class StaticCode1{ static{ //第4步。由第3步触发。 System.out.print
2021-01-23 23:04:39
944
原创 java.util.concurrent介绍
java.util.concurrent 包含许多线程安全、测试良好、高性能的并发构建块。不客气地说,创建 java.util.concurrent 的目的就是要实现 Collection 框架对数据结构所执行的并发操作。通过提供一组可靠的、高性能并发构建块,开发人员可以提高并发类的线程安全、可伸缩性、性能、可读性和可靠性。如果一些类名看起来相似,可能是因为 java.util.concurrent 中的许多概念源自 Doug Lea 的 util.concurrent 库。JDK 5.0 中的并发改进
2021-01-23 22:43:43
3727
原创 Java数据结构和算法 — 递归
什么是递归,上面的小故事就是一个明显的递归。以编程的角度来看,程序调用自身的编程技巧称为递归( recursion)。百度百科中的解释是这样的:递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。1、递归的定义递归,就是在运行的过程中调用自
2021-01-23 21:50:12
172
原创 Java数据结构和算法 — 高级排序
1、希尔排序希尔排序是基于直接插入排序的,它在直接插入排序中增加了一个新特性,大大的提高了插入排序的执行效率。所以在讲解希尔排序之前,我们先回顾一下直接插入排序。①、直接插入排序直接插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。实现代码为:package com.ys.sort; public class InsertSort { public static int[] sort(int[] array){ int
2021-01-23 20:48:05
128
原创 Java数据结构和算法 — 无权无向图
1、图的定义我们知道,前面讨论的数据结构都有一个框架,而这个框架是由相应的算法实现的,比如二叉树搜索树,左子树上所有结点的值均小于它的根结点的值,右子树所有结点的值均大于它的根节点的值,类似这种形状使得它容易搜索数据和插入数据,树的边表示了从一个节点到另一个节点的快捷方式。而图通常有个固定的形状,这是由物理或抽象的问题所决定的。比如图中节点表示城市,而边可能表示城市间的班机航线。如下图是美国加利福利亚简化的高速公路网:①、邻接:如果两个顶点被同一条边连接,就称这两个顶点是邻接的,如上图 I 和
2021-01-23 20:27:28
206
原创 Java数据结构和算法 — 冒泡、选择、插入排序算法
1、冒泡排序这个名词的由来很好理解,一般河水中的冒泡,水底刚冒出来的时候是比较小的,随着慢慢向水面浮起会逐渐增大,这物理规律我不作过多解释,大家只需要了解即可。冒泡算法的运作规律如下:①、比较相邻的元素。如果第一个比第二个大,就交换他们两个。②、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数(也就是第一波冒泡完成)。③、针对所有的元素重复以上的步骤,除了最后一个。④、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。代
2021-01-22 23:20:43
104
原创 JAVA IO 流之字符流的缓冲区
1.缓冲区的出现提高了对数据的读写效率2.对应类:BufferedWriterBufferedReader缓冲区需要结合流才可以使用, 对流的功能进行了增强, 即对流的操作起到装饰作用使用缓冲区实现文本文件的写入和读取// 写入public class BufferedWriterDemo{ public static void main(String[] args) throws IOException { FileWriter fw = new FileWri
2021-01-22 23:05:23
158
原创 带你九浅一深理解Java Stream流水线
前面我们已经学会如何使用Stream API,用起来真的很爽,但简洁的方法下面似乎隐藏着无尽的秘密,如此强大的API是如何实现的呢?Pipeline是怎么执行的,每次方法调用都会导致一次迭代吗?自动并行又是怎么做到的,线程个数是多少?本节我们学习Stream流水线的原理,这是Stream实现的关键所在。首先回顾一下容器执行Lambda表达式的方式,以ArrayList.forEach()方法为例,具体代码如下:// ArrayList.forEach()public void forEach(Cons
2021-01-22 22:48:09
501
1
原创 Java Stream API入门篇
你可能没意识到Java对函数式编程的重视程度,看看Java 8加入函数式编程扩充多少功能就清楚了。Java 8之所以费这么大功夫引入函数式编程,原因有二:代码简洁,函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。多核友好,Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是调用一下parallel()方法。这一节我们学习stream,也就是Java函数式编程的主角。对于Java 7来说stream完全是个陌生东西,stream并不是某种数据结构,它只是数
2021-01-22 22:28:47
125
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅