java
十年少i
努力。
展开
-
接口与抽象类的区别--面试常问
接口与抽象类的区别的小视频原创 2020-08-19 10:53:52 · 207 阅读 · 0 评论 -
ArrayList 在循环时候调用remove()方法 合法吗?
1 正向循环删除的时候由于删除完一个元素后会进行元素移动,如果有一样的元素,会漏删第二个一样的元素。for循环正向删除,会遗漏连续重复的元素。2 反向循环删除不会出现漏删情况,并且多线程安全。总结:反向遍历删除,没有问题(单线程+多线程)。3 使用迭代器删除,如果调用List的remove()方法,会抛出异常,通过迭代器的源码解析,发现是由于删除后ModCount会增加 但expectedModCount不会增加这样在下边方法判断中就会由于这两个参数不相等而抛出异常。Iterator调用Array.原创 2020-08-16 10:29:33 · 445 阅读 · 0 评论 -
单例模式也有坑-快进来看看
饿汉式一般饿汉式加载所导致的弊端是可能我并不想使用实例但是实例已经被构造,相对于懒汉式的用则构造会造成内存的浪费,但是其实现方式很简单//饿汉式单例public class Hungry { //如此操作可能会浪费空间 private byte[] data1 =new byte[1024*1024]; private byte[] data2 =new byte[1024*1024]; private byte[] data3 =new byte[1024*1原创 2020-08-12 22:15:01 · 220 阅读 · 1 评论 -
探秘 Spring IoC
前言:在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。齿轮组中齿轮之间的啮合关系,与软件系统中对象之间的耦合关系非常相似。对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础。为了解决对象之间的耦合度过高的问题,软件专家Michael Mattson提出了IOC理论,用来实现对象之间的“解耦”,目前这个理论已经被成功地应用到实践当中,很多的J2EE项目均采用了IOC框架产品Spring。一. 什么是控制反转(IoC原创 2020-08-11 20:18:18 · 167 阅读 · 0 评论 -
探秘 Spring AOP到底是JDK 还是 CGLib动态代理(源码分析)
一、什么是AOP?与OOP相比,面向切面,传统的oop开发中的代码逻辑是至上而下的,在这个过程中 会产生一些横切性的问题,会散落在代码的各个角落中,造成难以维护,耦合度高,aop编程思想就是将这些散落的代码分离出来,独立的封装出来,达到解耦的目的,提高代码的重用性和效率。在日常的软件开发中,拿日志来说,一个系统软件的开发都是必须进行日志记录的,不然万一系统出现什么bug,你都不知道是哪里出了问题。举个小栗子,当你开发一个登陆功能,你可能需要在用户登陆前后进行权限校验并将校验信息(用户名,密码,请原创 2020-08-11 19:50:33 · 1317 阅读 · 0 评论 -
浅析-SpringBean
前言在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean。简单地讲,bean 就是由 IOC 容器初始化、装配及管理的对象,除此之外,bean 就与应用程序中的其他对象没有什么区别了。而 bean 的定义以及 bean 相互间的依赖关系将通过配置元数据来描述。Spring中的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Servlet线程来处理请求,引入原创 2020-08-10 22:17:47 · 173 阅读 · 0 评论 -
Condition接口示例与实现分析
Condition – 条件任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,这些方法与synchronized同步关键字配合,可以实现等待/通知模式。换而言之,synchronized关键字想要实现等待/通知模式,需要调用以上的四种方法。然后我们的Condition接口也提供了能够实现等待/通知模式,是与Lock配合实现的。但是二者在使用方式上以及功能原创 2020-08-07 22:38:24 · 309 阅读 · 0 评论 -
LockSupport工具
当需要阻塞或唤醒一个线程的时候,都会使用LockSupport工具类来完成相应工作。LockSupport定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能,而LockSupport也成为构建同步组件的基础工具。LockSupport定义了一组以park开头的方法用来阻塞当前线程,以及unpark(Thread thread)方法来唤醒一个被阻塞的线程。Park有停车的意思,假设线程为车辆,那么park方法代表着停车,而unpark方法则是指车辆启动离开,这些方法以及描述如表所示。..原创 2020-08-06 22:41:39 · 137 阅读 · 0 评论 -
Lock接口与队列同步器AQS
Lock接口与synchronized锁对比在Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性使用synchronized关键字将会隐式地获取锁,但是它将锁的获取和释原创 2020-08-06 22:24:01 · 156 阅读 · 0 评论 -
happens-before详解
happens-before是JMM最核心的概念。对应Java程序员来说,理解happens-before是理解JMM的关键。(对于做好程序员来说,理解世间万物都是关键)首先,从JMM设计者的角度,在设计JMM时,需要考虑两个关键因素。程序员对内存模型的使用。程序员希望内存模型易于理解、易于编程。程序员希望基于一个强内存模型来编写代码。编译器和处理器对内存模型的实现。编译器和处理器希望内存模型对它们的束缚越少越好,这样它们就可以做尽可能多的优化来提高性能。编译器和处理器希望实现一个弱内存模..原创 2020-08-06 12:51:59 · 1790 阅读 · 0 评论 -
concurrent包的实现
由于Java的CAS同时具有volatile读和volatile写的内存语义,因此Java线程之间的通信现在有了下面4种方式。1)A线程写volatile变量,随后B线程读这个volatile变量。2)A线程写volatile变量,随后B线程用CAS更新这个volatile变量。3)A线程用CAS更新一个volatile变量,随后B线程用CAS更新这个volatile变量。4)A线程用CAS更新一个volatile变量,随后B线程读这个volatile变量。Java的CAS会使用现代处理..原创 2020-08-06 12:30:36 · 258 阅读 · 0 评论 -
volatile的内存语义
前言当声明共享变量为volatile后,对这个变量的读/写将会很特别。为了揭开volatile的神秘面纱,下面将介绍volatile的内存语义及volatile内存语义的实现。volatile的应用与底层原理详见:《volatile的应用与底层原理》volatile的特性理解volatile特性的一个好方法是把对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步。下面通过具体的示例来说明,示例代码如下。class VolatileFeaturesExampl原创 2020-08-06 12:01:38 · 404 阅读 · 0 评论 -
处理器(CPU)是如何实现原子性操作的?总线锁与缓存锁
处理器如何实现原子操作(1)使用总线锁保证原子性第一个机制是通过总线锁保证原子性。如果多个处理器同时对共享变量进行读改写操作(i++就是经典的读改写操作),那么共享变量就会被多个处理器同时进行操作,这样读改写操作就不是原子的,操作完之后共享变量的值会和期望的不一致。举个例子,如果i=1,我们进行两次i++操作,我们期望的结果是3,但是有可能结果是2,如图所示。原因可能是多个处理器同时从各自的缓存中读取变量i,分别进行加1操作,然后分别写入系统内存中。那么,想要保证读改写共享变量的操作是原子的,就原创 2020-08-05 21:59:53 · 3671 阅读 · 4 评论 -
Java如何实现原子操作--CAS与锁机制
使用循环CAS实现原子操作JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止.那么什么是CAS呢?CAS的定义一个线程失败或挂起并不会导致其他线程也失败或挂起,那么这种算法就被称为非阻塞算法。而CAS就是一种非阻塞算法实现,也是一种乐观锁技术,它能在不使用锁的情况下实现多线程安全,所以CAS也是一种无锁算法。CAS [公式] 比较并交换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技原创 2020-08-05 21:35:51 · 435 阅读 · 0 评论 -
synchronized的实现原理与应用
在多线程并发编程中synchronized一直是元老级角色,很多人都会称呼它为重量级锁。但是,随着Java SE 1.6对synchronized进行了各种优化之后,有些情况下它就并不那么重了。下面详细介绍Java SE 1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。利用synchronized实现同步的基础:Java中的每一个对象都可以作为锁。具体表现为以下3种形式。* 对于普通同步方法,锁是当前实例对象。* 对于静态同步方法,锁是当前类的Cla原创 2020-08-05 21:20:40 · 153 阅读 · 0 评论 -
浅析Java内存模型
Java内存模型的抽象结构Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。Java内存模型的抽象示原创 2020-08-05 09:57:40 · 103 阅读 · 0 评论 -
共享锁和排他锁以及乐观锁
共享锁如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。排他锁排他锁(X锁):用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。我们在操作数据库的时候,可能会由于并发问题而引起的数据的不一致性(数据冲突)乐观锁乐观锁不是数据库自带的,需要我们自己去实现。乐观锁是原创 2020-08-05 08:34:15 · 624 阅读 · 0 评论 -
volatile的应用以及底层实现原理
volatile的定义Java语言规范第3版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。排他锁又称写锁,当某个资源被上排他锁时,只能有一个线程占用,其他线程如果想要访问该资源只能等待。在了解volatile实现原理之前,我们先来看下与原创 2020-08-05 08:27:23 · 462 阅读 · 1 评论 -
死锁问题详解
锁是个非常有用的工具,运用场景非常多,因为它使用起来非常简单,而且易于理解。但同时它也会带来一些困扰,那就是可能会引起死锁,一旦产生死锁,就会造成系统功能不可 用。让我们先来看一段代码,这段代码会引起死锁,使线程t1和线程t2互相等待对方释放锁。public class DeadLockDemo { private static String A = "A"; private static String B = "B"; publi原创 2020-08-04 23:04:32 · 1325 阅读 · 0 评论 -
并发编程----上下文切换
前言:即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。什么是上下文切换?CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。举个例子:.原创 2020-08-04 22:11:35 · 246 阅读 · 0 评论 -
JVM--类加载机制与类加载器
类的加载机制运行期类加载。即在语言里面,类型的加载、连接和初始化过程都是在程序运行期完成的,从而通过牺牲一些性能开销来换取Java程序的高度灵活性什么是运行期,什么是编译期?编译期是指编译器将源代码翻译为机器能识别的代码,Java被编译为Jvm认识的**字节码文件,运行期 则是指Java代码的 运行 过程。JVM运行期 动态加载 + 动态连接 -> Java的动态扩展特性类加载的生命周期:1.加载加载阶段虚拟机完成的事:通过类的全限定名来获取定义此类的二进制字节流。将该二进制原创 2020-08-03 21:27:48 · 256 阅读 · 0 评论 -
仿写Servlet,实现servlet原理(涉及反射)
个人码云:https://gitee.com/zzz444/imitateServlet/可以克隆下载学习;目录结构package com.james.test;import com.james.interfaces.HttpServlet;import com.james.interfaces.WebServlet;@WebServlet("/test")public class TestMyServlet implements HttpServlet { @Override原创 2020-08-03 14:09:30 · 308 阅读 · 0 评论 -
现代最前沿成果之一---G1垃圾收集器器详解
G1是什么?原创 2020-08-02 10:24:21 · 775 阅读 · 0 评论 -
面试官99.99%会严刑拷打的几种垃圾收集器,各自的优缺点,包括原理,流程,优缺点。
1)几种垃圾收集器:Serial收集器: 单线程的收集器,收集垃圾时,必须stop the world(即只运行GC线程,暂停所有用户线程),用户体验感不好,使用复制算法,但是并未过时,到现在为止,依然是虚拟机运行在Client模式下的默认新生代收集器。ParNew收集器: Serial收集器的多线程版本,实际上与Serial收集器共用了很多代码,也需要stop the world,使用复制算法。Parallel Scavenge收集器: 新生代收集器,复制算法的收集器,并发的多线程收集器原创 2020-08-01 22:27:55 · 250 阅读 · 0 评论 -
为什么有full GC还会发生oom(OutOfMemoryError)
JVM 有fullGC为什么还会出现oom(OutOfMemoryError)?既然在触发full gc的时候,年老代和持久代都会被清理,那么为什么还会出现oom问题?而且对于强引用,当内存空间不足,java虚拟机宁愿抛出oom错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题;那么full gc机制的存在有何意义?还是说fgc主要针对的是驻扎在老年的的软引用? 既然如此,对于四种引用的方式如何抉择?总不能所有对象都创建引用队列使用软引用或弱引用吧?举个栗子:为什么我请了佣原创 2020-08-01 21:15:23 · 2293 阅读 · 0 评论 -
JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代,Minor GC、Major GC和Full GC之间的区别
一、可达性分析算法(GC Roots)有一种引用计数法,可以用来判断对象被引用的次数,在任何某一具体时刻,如果引用次数为0,则代表可以被回收。这种实现方式比较简单,但对于循环引用的情况束手无策,所以 Java 采用了可达性分析算法。即判断某个对象是否与 GC Roots 的这类对象之间的路径可达,若不可达,则有可能成为回收对象,被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。具体详情可以看我另外一原创 2020-08-01 20:47:31 · 12184 阅读 · 0 评论 -
什么情况下会发生堆内存溢出,栈内存溢出,结合实例说明
转载自:https://blog.csdn.net/qq_31615049/article/details/82980799一、 栈溢出(StackOverflowError)栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口灯信息。局部变量表又包含基本数据类型,对象引用类型(局部变量表编译器完成,运行期间不会变化)所以我们可以理解为栈溢出就是方法执行是创建的栈帧请求的深度超过了栈能给予的最大深度。最有可能的就是:方法转载 2020-08-01 20:06:08 · 2081 阅读 · 0 评论 -
深入讲解JVM垃圾回收算法思想及全过程
垃圾回收算法由于垃圾收集算法的实现涉及大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,因此只是深入讲解以下几种算法的思想。标记清除算法:先标记出需要回收的对象,再清除回收。是一种最基础的收集算法。标记和清除两个过程的并不高,另一个问题就是空间问题:清理完成后产生大量的不连续的内存碎片,以后分配大的对象的时候,无法找到足够的连续内存而不得不提前触发另一次的垃圾处理动作。* 回收前先标记出需要回收的对象(黑色方块)回收后有大量的非连续的碎片空间(图中白色方块为未使用的)原创 2020-08-01 11:57:07 · 513 阅读 · 0 评论 -
JAVA虚拟机--JVM之旅02 判断对象已”死“(想要对象留下,就给它一个自救的机会)
对象已”死“吗?判断方法:*原创 2020-08-01 06:59:37 · 271 阅读 · 0 评论 -
JAVA虚拟机--JVM之旅01对象创建,内存分配,内存布局,访问定位(想要对象就new一个)
JVM 一运行时数据区域简单介绍:方法区:和Java堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等。堆:堆是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,再虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。虚拟机栈:其生命周期与线程相同。其描述的是Java方法执行的内存模型原创 2020-07-31 21:59:42 · 199 阅读 · 0 评论 -
带你一文搞懂Hash算法解决冲突的四种方法
Hash算法解决冲突的方法一般有以下几种常用的解决方法1, 开放定址法:所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入 公式为:fi(key)= (f(key)+di) MOD m (di=1,2,3,……,m-1)※用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址原创 2020-07-31 17:20:08 · 808 阅读 · 0 评论 -
复习:Java继承·反射·代理 面试基础笔记(接口与抽象类区别)
继承覆盖方法也就是重写不改变预期的行为如何访问到父类的数据 super子类构造器通过super来调用父类构造器而且super必须是第一行有效代码如果我们没有显示调用 那么会自动调用父类的无参构造器如果父类里没有无参构造器, 但有其他的显示构造器 那么将会报错super 和this 的对比多态子类可以赋值给父类类型执行的会执行动态绑定 看执行那个类的方法方法调用参照核心卷强制类型转化将一个子类的引用赋给一个超类变量, 编译器是允许的。但将一个超类的引原创 2020-07-29 23:02:17 · 251 阅读 · 0 评论 -
复习:Java核心卷I面试基础笔记
8个基本的数据类型int32位4个字节正负20亿不能存手机号long64位8个字节float32位4个字节34.0fdouble64位8个字节short16位2个字节bytechar16位booleanfinal 关键字final: Final用于修饰类、成员变量和成员方法。final修饰的类,不能被继承(String、StringBuilder、StringBuffer、Math,不可变类),其原创 2020-07-28 22:40:00 · 151 阅读 · 0 评论 -
复习:二叉树多叉树面试基础笔记(待完善)
多叉树二叉树每个节点最多拥有两个子节点每个节点最多有一个父节点只有一个根节点遍历前序遍历中序遍历后序遍历层次遍历搜索二叉树左边比根小右边比根大查找时间 最优 Ologn ~ On 不太稳定平衡二叉树旋转 如何旋转 如何平衡最小不平衡子树LL型LR型任何一个节点 左右子树高度差不超过1RR型RL型自己画一下...原创 2020-07-28 08:59:57 · 160 阅读 · 0 评论 -
复习:Map面试基础笔记 (狂虐HashMap)
Map采用了 Key-value键值对映射的方式进行存储1 key在Map里面是唯一的但是value可以重复一 个key对应一个value。2 key是无序、唯一的3 value是无序不唯一的HashMap(重中之重)查找 时间复杂度都要小,无限接近O(1)是可以序列化的是线程不安全的底层主要是基于数组和链表实现的,它之所以有相当快的查询速度主要是因为它是通过计算散列码来决定存储位置的。(这里本人之前也有过简单的HashMap简介可以了解下:https://blog.c原创 2020-07-27 22:42:14 · 204 阅读 · 0 评论 -
复习:链表面试基础笔记
链表查找麻烦插入和删除简单可以定点删除和插入物理存储空间可以是非连续的,内存利用率高,不会浪费内存(可以使用内存中细小的不连续空间(大于node节点的大小),并且在需要空间的时候才创建空间)无限定长度,容易扩展,灵活度高。节点一般是类 ,一些语言中是结构体删除是用指针指向其他节点他是线程不安全的查询效率不好 On头节点问题链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。这里有个地方要注意原创 2020-07-27 22:06:40 · 122 阅读 · 0 评论 -
复习:数组面试总结(笔记)
数组数组的特性:存储空间是连续的长度是不可变的只能存储 相同的类型(不严谨)可以通过下标访问数组的内容 a[10] 时间复杂度为O1每个元素的默认值为‘零’值 (0 或 null 或 false)-> 一个对象的基本的数据域的初始化也是这样的例如 Student 类中的username属性 默认值ArrayList自动扩容长度有限(int的最大值)默认初始容量为10每次扩容原来的1.5倍(因为源码中是 a+(a>>1) 是原来值+原来值右移一位,也就是原来值除原创 2020-07-27 21:10:09 · 117 阅读 · 0 评论 -
Java反射 Method Class.getMethod(String name, Class... parameterTypes) 转载自大佬
本文转自: https://blog.csdn.net/Handsome_fan/article/details/54846959 感谢大佬Method Class.getMethod(String name, Class<?>... parameterTypes)的作用是获得对象所声明的公开方法该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型。person.getClass().getMethod(“Speak”, n.转载 2020-07-13 22:20:29 · 776 阅读 · 0 评论 -
java中getClass()方法简介 (转载自大神)
转载自这位大佬 https://blog.csdn.net/expect521/article/details/79139829学习到了很多,棒棒哒!getClass() 返回此 Object 的运行时类。public class Test { public static void main(String[] args) { Person p = new Person(1,"刘德华"); System.out.println(p.getClass()); .转载 2020-07-13 22:10:36 · 1236 阅读 · 0 评论 -
Set集合 你不知道的去重和比较方法,进来了解一下吧!
Set集合特点: 无序 集合中的元素不重复(是没有下标的,对比map来说,只有值,没有键)HashSet第一个特点:hashset具有去重功能例: 创建一个hashset 保存 a,a,b去重且无序(结果并不是按照输出顺序打印)!!注意: 打印对象不会自动去重 需要重写equals和hashcode方法 去重系统类的对象时不用重写去重: 当添加到Set的对象 Hash...原创 2020-02-12 21:18:26 · 584 阅读 · 0 评论