![](https://img-blog.csdnimg.cn/20210429095556811.jpeg?x-oss-process=image/resize,m_fixed,h_224,w_224)
Java学习笔记
文章平均质量分 88
Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程
GeorgiaStar
世上无难事,只要肯放弃
展开
-
你的八股文可能已经过时了
Java中接口的目的是定义公开的API,而隐藏实现细节,所以在JDK8以前都不支持默认和静态方法。但是出于便捷性的考虑,JDK8开始支持在接口定义一个方法的默认实现,这样当一个接口有大量实现类的情况下,可以在不破坏原有实现的前提下迭代API。JDK8中接口类的默认实现解决了模型抽象中的很多问题,随之而来的问题是如果在接口的默认方法中需要共享一些代码段,只能将这些代码段抽象出一个新的函数。如果这个函数是静态的(JDK8支持接口中定义静态函数),那么在函数里就无法访问其他非静态API。原创 2024-06-06 10:40:21 · 673 阅读 · 0 评论 -
用代码实现生产者消费者模型
用代码实现生产者消费者模型,3个生产者每隔3秒生产1个单位的数据,2个消费者每隔1秒消费一个单位的数据,共享资源有界。要求不能出现死锁或者占用CPU不释放的情况。原创 2021-09-06 19:02:47 · 816 阅读 · 0 评论 -
AQS与Synchronized异曲同工的加锁流程
在并发多线程的情况下,为了保证数据安全性,一般我们会对数据进行加锁,通常使用Synchronized或者ReentrantLock同步锁。Synchronized是基于JVM实现,而ReentrantLock是基于Java代码层面实现的,底层是继承的AQS原创 2023-02-20 15:06:02 · 524 阅读 · 0 评论 -
Java 8的函数式接口使用示例
有且只有一个抽象方法的接口被称为函数式接口,函数式接口适用于函数式编程的场景,Lambda就是Java中函数式编程的体现,可以使用Lambda表达式创建一个函数式接口的对象,一定要确保接口中有且只有一个抽象方法,这样Lambda才能顺利的进行推导。原创 2023-02-15 16:02:28 · 1086 阅读 · 0 评论 -
刨根问底:Java动态运行Groovy可能有哪些坑
Groovy代码能够与Java代码很好地结合,也能用于扩展现有代码。相对于Java,它在编写代码的灵活性上有非常明显的提升。Groovy是动态编译语言,广泛用作脚本语言和快速原型语言,主要优势之一就是它的生产力。Groovy代码通常要比Java代码更容易编写,而且编写起来也更快,这使得它有足够的资格成为开发工作包中的一个附件。...原创 2022-07-13 13:14:59 · 5489 阅读 · 0 评论 -
为什么需要JMM(Java内存模型)
为什么需要 JMM,它试图解决什么问题?Java 是最早尝试提供内存模型的语言,这是简化多线程编程、保证程序可移植性的一个飞跃。早期类似 C、C++ 等语言,并不存在内存模型的概念(C++ 11 中也引入了标准内存模型),其行为依赖于处理器本身的内存一致性模型,但不同的处理器可能差异很大,所以一段 C++ 程序在处理器 A 上运行正常,并不能保证其在处理器 B 上也是一致的。即使如此,最初的 ......转载 2020-03-28 10:25:03 · 2184 阅读 · 0 评论 -
用自定义类加载器实现Java类隔离
类隔离就是让不同模块的jar包用不同的类加载器加载,要做到这一点,就需要让JVM能够使用自定义的类加载器加载我们写的类以及其关联的类。原创 2022-06-04 15:43:49 · 2850 阅读 · 4 评论 -
JVM运行时数据区域——为什么jdk8用元空间替换了永久代
JVM 运行时数据区域(堆和栈存哪些内容、堆和栈的区别、方法区存哪些内容、为什么 jdk8 用元空间替换了永久代)原创 2022-03-31 17:57:30 · 1658 阅读 · 0 评论 -
死磕CMS垃圾收集器
面试官:今天还是来聊聊CMS垃圾收集器呗?候选者:嗯啊…候选者:如果用Seria和Parallel系列的垃圾收集器:在垃圾回收的时,用户线程都会完全停止,直至垃圾回收结束!候选者:CMS的全称:Concurrent Mark Sweep,翻译过来是「并发标记清除」,是老年代垃圾收集器候选者:用CMS对比上面的垃圾收集器(Seria和Parallel和parNew):它最大的不同点就是「并发」:在GC线程工作的时候,用户线程「不会完全停止」,用户线程在「部分场景下」与GC线程一起并发执行。候选者:转载 2021-11-09 17:19:13 · 393 阅读 · 0 评论 -
学透并发编程——LeetCode多线程协作经典题
LeetCode上专门的多线程题目版块,本文通过解决几道leetCode上的多线程协作交替打印的编程题,来加深对并发编程的理解,并训练一下并发编程思想。原创 2021-11-09 16:53:07 · 1463 阅读 · 0 评论 -
再谈线程安全
线程安全“线程安全”不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。假设某个线程把数据处理到一半,觉得很累,就去休息了一会,回来准备接着处理,却发现数据已经被修改了,不是自己离开时的样子了。可能被其它线程修改原创 2021-08-17 14:08:27 · 215 阅读 · 0 评论 -
Java并发编程——CompletableFuture类
从Future接口开始java.util.concurrent.Future接口是Java 5添加的类,用来描述一个异步计算的结果。可以使用该接口的isDone()方法检查计算是否完成,或者使用get()阻塞住调用线程,直到计算完成返回结果,也可以使用cancel()方法停止任务的执行。ExecutorService es = Executors.newFixedThreadPool(10);Future<Integer> f = es.submit(() ->{ /原创 2021-07-27 15:18:39 · 4070 阅读 · 0 评论 -
本地方法栈、JVM栈、本地内存和JVM Heap的区别与关系
在Java出现之前,像C/C++这样的编译型语言写出来的代码都是编译为机器码(machine code)后直接运行的,machine code其实就是native code,直接和操作系统交互。对于内存,主要分三部分:1)存储可执行代码(冯·诺依曼的存储程序的思想),即编译后的machine code;2)用来保存代码执行时用到的局部变量,即stack;3)代码执行时,动态找操作系统申请(最终要归还给操作系统)的heap;对于Heap的分配和归还都是由程序代码手工维护的。如下图所示,写一段C++原创 2021-05-24 21:51:12 · 2787 阅读 · 3 评论 -
写时复制(Copy-On-Write)思想在Java中的应用
前言写时复制(Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这个过程对其他的调用者是透明的(transparently)。此作法的主要优点是如果调用者没有修改该资源,就不会有副本(private copy)被建立,因原创 2021-05-20 20:01:21 · 1547 阅读 · 6 评论 -
读完《深入理解Java虚拟机》后记录几个问题
以下总结的问题都是在针对HotSpot虚拟机展开讨论,这些问题其实都可以在下面这本秘籍中找到答案——《深入理解Java虚拟机》几乎是每一个Java开发者必备宝典原创 2021-05-14 17:20:59 · 474 阅读 · 0 评论 -
Java中的四大引用
Java对引用的定义无论是通用引用计数算法判断对象的引用数据,还是通过可达性分析算法判断对象的引用链是否可达,判定对象是否存活都与“引用”有关。在JDK1.2之前,Java中的引用定义很传统:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。这种定义很纯粹,但是太过狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态,对于如何描述一些“食之无味,弃之可惜”的对象就显得无能为力。我们希望能描述这样一类对象:当内存空间还足够时,则能保留在内存中,如果原创 2021-03-04 20:47:56 · 323 阅读 · 1 评论 -
ThreadLocal及其内存泄露分析
ThreadLocalThreadLocal是一个线程本地变量,作用主要是做数据隔离。ThreadLocal中填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的,每个线程维护自己的变量副本,多个线程互相不可见,因此多线程操作该变量不必加锁,适合不同线程使用不同变量值的场景。数据隔离有什么用,用在哪些场景?一个典型的应用场景就是Spring事务,事务是和线程绑定起来的,Spring框架在事务开始时会给当前线程绑定一个JDBC Connection,整个事务过程都是使用该线程绑定的conne原创 2020-08-17 20:33:09 · 515 阅读 · 0 评论 -
Java堆内存是线程共享的吗
转载声明:Java堆内存是线程共享的!面试官:你确定吗?Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或多或少的对JVM有一些了解。可以说,关于JVM的相关知识,基本是每个Java开发者必学的知识点,也是面试的时候必考的知识点。在JVM的内存结构中,比较常见的两个区域就是堆内存和栈内存(如无特指,本文提到的栈均指的是虚拟机栈),关于堆和栈的区别,很多开发者也是如数家珍,有很多书籍,或者网上的文章大概都是这样介绍的:堆是线程共享的内转载 2020-07-22 15:55:13 · 1891 阅读 · 0 评论 -
Java对函数式编程的支持
背景现在主流的编程范式主要有三种,面向过程、面向对象和函数式编程。函数式编程并非一个很新的东西,早在 50 多年前就已经出现了。近几年,函数式编程越来越被人关注,出现了很多新的函数式编程语言,比如Clojure、Scala、Erlang等。一些非函数式编程语言也加入了很多特性、语法、类库来支持函数式编程,比如Java、Python、Ruby、JavaScript等。除此之外,Google Guava也有对函数式编程的增强功能。函数式编程因其编程的特殊性,仅在科学计算、数据处理、统计分析等领域,才能更好转载 2020-06-01 21:20:47 · 780 阅读 · 0 评论 -
一步一步实现优雅重试
重试的作用对于重试是有场景限制的,不是什么场景都适合重试,比如参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。远程调用超时、网络突然中断可以重试。在微服务治理框架中,通常都有自己的重试与超时配置,比如dubbo可以设置retries=1、timeout=500调用失败只重试1次,超过500ms调用仍未返回则调用失败。对于开发过网络应用程序的程序员来说,重试并不陌生,由于网络的拥堵和波...原创 2020-04-29 21:18:48 · 1218 阅读 · 0 评论 -
Java阻塞延迟队列DelayQueue原理及使用
DelayQueue队列中每个元素都有一个过期时间,并且队列是个优先级队列,当从队列获取元素的时候,只有过期元素才会出队。原创 2020-04-23 21:26:27 · 12519 阅读 · 0 评论 -
再见队列同步器——CountDownLatch实现分析
CountDownLatch使用场景CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有框架服务之后执行。CountDownLatch在多线程并发编程中充当一个计时器的功能。典型的使用例子如下:public class CountDownLatchTest { priv...原创 2020-04-02 11:15:31 · 319 阅读 · 0 评论 -
又见队列同步器——Condition接口的实现
Condition接口与Object监视器方法任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、nofity()以及notifyAll()方法,这些方法与synchronized同步关键字配合,可以实现等待/通知模式。Condition接口也提供了类似Object的监视器方法,与Lock配合也可以实...原创 2020-03-22 21:00:41 · 708 阅读 · 0 评论 -
Java对synchronized锁的实现与优化
当线程释放锁时,JMM(Java Memory Model)会把该线程对应的本地内存中的共享变量刷新到主内存中。当线程获取锁时,JMM会把该线程对应的本地内存置为无效,从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。对象在内存中存储的布局可以分为三块:对象头、实例数据和对齐填充。...原创 2020-03-21 14:34:11 · 1167 阅读 · 1 评论 -
从源码角度理解ReentrantLock及队列同步器(AQS)
JDK中独占锁(排他锁)的实现除了使用关键字synchronized外,还可以使用ReentrantLock。虽然在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。ReentrantLock常常对比着synchronized来分析,我们先对比着来看然后再一点...原创 2020-03-08 11:54:51 · 999 阅读 · 0 评论 -
彻底理解Java反射以及动态代理中对反射的应用
反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使...原创 2020-03-01 23:23:43 · 3170 阅读 · 6 评论 -
彻底理解ConcurrentHashMap
1、ConcurrentHashMap概述第1节介绍了HashMap的数据结构及原理,不过遗憾的是,HashMap不是线程安全的。也就是说,在多线程环境下,操作HashMap会导致各种各样的线程安全问题,比如在HashMap扩容重哈希时出现的死循环问题,脏读问题等。HashMap的这一缺点往往会造成诸多不便,虽然在并发场景下HashTable和由同步包装器包装后的HashMap(Collecti...原创 2020-02-21 17:02:07 · 796 阅读 · 0 评论 -
彻底理解HashMap及LinkedHashMap
HashMap是Map族中最为常用的一种,也是 Java Collection Framework 的重要成员。HashMap和双向链表合二为一即是LinkedHashMap。所谓LinkedHashMap,其落脚点在HashMap,因此更准确地说,它是一个将所有Node节点链入一个双向链表的HashMap。ConcurrentHashMap是java.util.concurrent包的重要成员,...原创 2020-02-18 14:06:55 · 5013 阅读 · 5 评论 -
从一个Logger异常开始梳理Java日志体系
从一个启动异常开始SpringBoot项目在启动时报堆栈溢出,错误如下。Exception in thread "main" java.lang.StackOverflowError at org.apache.logging.log4j.util.StackLocator.getCallerClass(StackLocator.java:108) at org.apache....原创 2020-01-01 11:51:36 · 1095 阅读 · 0 评论 -
Java中的NIO与Netty框架
前言 随着移动互联网的爆发性增长,小明公司的电子商务系统访问量越来越大,由于现有系统是个单体的巨型应用,已经无法满足海量的并发请求,拆分势在必行。 在微服务的大潮之中, 架构师通常会把系统拆分成了多个服务,根据需要部署在多个机器上,这些服务非常灵活,可以随着访问量弹性扩展。 世界上没有免费的午餐, 拆分成多个“微服务”以后虽然增加了弹性,但也带来了一个巨大的挑战:各个服务之间互相调用的开销原创 2017-12-16 12:08:14 · 5869 阅读 · 1 评论 -
RPC框架原理探讨
摘要: 本文阐述了RPC框架与远程调用的产生背景,介绍了RPC的基本概念和使用背景,之后手动实现了简易的RPC框架并佐以实例进行演示,以便让各位看官对RPC有一个感性、清晰和完整的认识,最后讨论了RPC框架几个较为重要问题。总之,RPC框架的精髓在于动态代理和反射,通过它们使得远程调用“本地化”,对用户透明且友好...转载 2018-05-02 20:23:14 · 529 阅读 · 0 评论 -
分布式架构的演进过程
一、什么是分布式架构分布式系统(distributed system) 是建立在网络之上的软件系统。 内聚性:是指每一个数据库分布节点高度自治,有本地的数据库管理系统。 透明性:是指每一个数据库分布节点对用户的应用来说都是透明的,看不出是本地还是远程。在分布式数据系统中,用户感觉不数据是分布的,即用户不须知道关系是否分割,有无副本,数据存在于那个站点以及事物在哪个站点上执行。 简单来说:...转载 2018-07-08 11:50:36 · 990 阅读 · 0 评论 -
JAVA中的动态代理
代理模式&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代理模式的英文叫做Proxy或Surrogate,中文都可译为“代理”,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用 。代理就是为其他对象提供一个代理以控制对某个对象的访问。比如火车票代...原创 2018-07-28 14:30:33 · 3936 阅读 · 1 评论 -
Java的Lock接口与读写锁
一、Lock接口与synchronized关键字 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但是有些锁可以允许多个线程并发的访问共享资源,比如读写锁)。在Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能的,而Java SE 5之后,并发包中新增了...原创 2018-07-15 14:21:02 · 3561 阅读 · 0 评论 -
理解Java ClassLoader
ClassLoader是Java最为神秘的技术之一,无数人被它伤透了脑筋,摸不清门道究竟在哪里。网上的文章也是一篇又一篇,经过本人的亲自鉴定,绝大部分内容都是在误导别人。本文我带读者彻底吃透 ClassLoader,以后其它的相关文章你们可以不必再细看了。ClassLoader 做什么的?顾名思义,它是用来加载 Class 的。它负责将 Class 的字节码形式转换成内存形式的 Class 对...转载 2019-01-05 13:16:42 · 836 阅读 · 1 评论 -
Java中的CAS
CAS的无锁思想众所周知,Java中对并发控制的最常见方法就是锁,锁能保证同一时刻只能有一个线程访问临界区的资源,从而实现线程安全。然而,锁虽然有效,但采用的是一种悲观的策略。它假设每一次对临界区资源的访问都会发生冲突,当有一个线程访问资源,其他线程就必须等待,所以锁是会阻塞线程执行的。当然,凡事都有两面,有悲观就会有乐观。而无锁就是一种乐观的策略,它假设线程对资源的访问是没有冲突的,同时所有...原创 2019-06-10 21:06:01 · 2798 阅读 · 2 评论 -
Java代码编译过程简述
Javac编译器,能将一种语言规范转化成另外一种语言规范,通常编译器都是将便于人理解的语言规范转化成机器容易理解的语言规范,如C/C++或者汇编语言都是将源代码直接编译成目标机器码,这个目标机器代码是CPU直接执行的指令集合。这些指令集合也就是底层的一种语言规范。原创 2017-02-05 11:31:14 · 23520 阅读 · 6 评论 -
彻头彻尾理解单例模式及其在多线程环境中的应用
摘要: 本文首先概述了单例模式产生动机,揭示了单例模式的本质和应用场景。紧接着,我们给出了单例模式在单线程环境下的两种经典实现:饿汉式 和懒汉式,但是饿汉式是线程安全的,而懒汉式是非线程安全的。在多线程环境下,我们特别介绍了五种方式来在多线程环境下创建线程安全的单例,即分别使用synchronized方法、synchronized块、静态内部类、双重检查模式 和Thr转载 2017-04-30 11:43:02 · 13164 阅读 · 4 评论 -
Java后端易忽略的问题
经过多种渠道的搜集,对Java后端程序员经常忽略的一些概念问题作一个整理。1、有状态bean和无状态bean 有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的,在不同方法调用间不保留任何状态。 无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象,不能保存数据,是不变类,是原创 2017-10-15 12:13:04 · 478 阅读 · 0 评论 -
Java性能优化:30个小细节,提升Java代码运行效率
代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但是,吃的小虾米一多之后,鲸鱼就被喂饱了。 代码优化也是一样,如果项目着眼于尽快无BUG上线,那么此时可以抓大放小,代码的细节可以不精打细磨;但是如果有足够的时间开发、维护代码,这时候就必须考虑每个可以优转载 2017-10-08 12:35:31 · 5096 阅读 · 0 评论