![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Java基础
Java基础
Andrew.J
以终为始,闭环迭代,持续提高。
展开
-
如何手写一个消息队列和延迟消息队列?
第一次听到“消息队列”这个词时,不知你是不是和我反应一样,感觉很高阶很厉害的样子,其实当我们了解了消息队列之后,发现它与普通的技术类似,当我们熟悉之后,也能很快地上手并使用。 典型回答 消息队列的使用场景有很多,最常见的使用场景有以下几个。 1.商品秒杀 比如,我们在做秒杀活动时,会发生短时间内出现爆发式的用户请求,如果不采取相关的措施,会导致服务器忙不过来,响应超时的问题,轻则会导致服务假死,重则会让服务器直接宕机,给用户带来的体验也非常不好。如果这个时候加上了消息队列,服务器接收到用户的所有请求后,先把原创 2020-11-30 10:28:44 · 268 阅读 · 0 评论 -
如何实现本地缓存和分布式缓存?
缓存(Cache)是指将程序或系统中常用的数据对象存储在像内存这样特定的介质中,以避免在每次程序调用时,重新创建或组织数据所带来的性能损耗,从而提高了系统的整体运行速度。 以目前的系统架构来说,用户的请求一般会先经过缓存系统,如果缓存中没有相关的数据,就会在其他系统中查询到相应的数据并保存在缓存中,最后返回给调用方。 典型回答 本地缓存是指程序级别的缓存组件,它的特点是本地缓存和应用程序会运行在同一个进程中,所以本地缓存的操作会非常快,因为在同一个进程内也意味着不会有网络上的延迟和开销。 本地缓存适用于单节原创 2020-11-30 10:05:56 · 721 阅读 · 0 评论 -
动态代理是如何实现的?JDK Proxy 和 CGLib 有什么区别?
90% 的程序员直接或者间接的使用过动态代理,无论是日志框架或 Spring 框架,它们都包含了动态代理的实现代码。动态代理是程序在运行期间动态构建代理对象和动态调用代理方法的一种机制。 动态代理的常用实现方式是反射。反射机制是指程序在运行期间可以访问、检测和修改其本身状态或行为的一种能力,使用反射我们可以调用任意一个类对象,以及类对象中包含的属性及方法。 但动态代理不止有反射一种实现方式,例如,动态代理可以通过 CGLib 来实现,而 CGLib 是基于 ASM(一个 Java 字节码操作框架)而非反射实原创 2020-11-27 17:36:57 · 169 阅读 · 0 评论 -
深克隆和浅克隆有什么区别?它的实现方式有哪些?
**浅克隆(Shadow Clone)**是把原型对象中成员变量为值类型的属性都复制给克隆对象,把原型对象中成员变量为引用类型的引用地址也复制给克隆对象,也就是原型对象中如果有成员变量为引用对象,则此引用对象的地址是共享给原型对象和克隆对象的。 简单来说就是浅克隆只会复制原型对象,但不会复制它所引用的对象,如下图所示: **深克隆(Deep Clone)**是将原型对象中的所有类型,无论是值类型还是引用类型,都复制一份给克隆对象,也就是说深克隆会把原型对象和原型对象所引用的对象,都复制一份给克隆对象,如下原创 2020-11-25 18:13:30 · 617 阅读 · 0 评论 -
谈谈你对锁的理解?如何手动模拟一个死锁?
在并发编程中有两个重要的概念:线程和锁,多线程是一把双刃剑,它在提高程序性能的同时,也带来了编码的复杂性,对开发者的要求也提高了一个档次。而锁的出现就是为了保障多线程在同时操作一组资源时的数据一致性,当我们给资源加上锁之后,只有拥有此锁的线程才能操作此资源,而其他线程只能排队等待使用此锁。 死锁是指两个线程同时占用两个资源,又在彼此等待对方释放锁资源,如下图所示: 死锁的代码演示如下: import java.util.concurrent.TimeUnit; public class LockExam原创 2020-11-25 15:55:05 · 113 阅读 · 0 评论 -
synchronized 和 ReentrantLock 的实现原理是什么?它们有什么区别?
在 JDK 1.5 之前共享对象的协调机制只有 synchronized 和 volatile,在 JDK 1.5 中增加了新的机制 ReentrantLock,该机制的诞生并不是为了替代 synchronized,而是在 synchronized 不适用的情况下,提供一种可以选择的高级功能。 synchronized 属于独占式悲观锁,是通过 JVM 隐式实现的,synchronized 只允许同一时刻只有一个线程操作资源。 在 Java 中每个对象都隐式包含一个 monitor(监视器)对象,加锁的过程原创 2020-11-25 15:34:29 · 137 阅读 · 0 评论 -
详解 ThreadPoolExecutor 的参数含义及源码执行流程
线程池是为了避免线程频繁的创建和销毁带来的性能消耗,而建立的一种池化技术,它是把已创建的线程放入“池”中,当有任务来临时就可以重用已有的线程,无需等待创建的过程,这样就可以有效提高程序的响应速度。但如果要说线程池的话一定离不开 ThreadPoolExecutor ,在阿里巴巴的《Java 开发手册》中是这样规定线程池的: 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的读者更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Ex原创 2020-11-25 14:32:30 · 377 阅读 · 0 评论 -
线程的状态有哪些?它是如何工作的?
线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在。一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源、更加轻量化,也因此被称为轻量级的进程。 线程的状态在 JDK 1.5 之后以枚举的方式被定义在 Thread 的源码中,它总共包含以下 6 个状态: ●NEW,新建状态,线程被创建出来,但尚未启动时的线程状态; ●RUNNABLE,就绪状态,表示可以运行的线程状态,它可能正在运行,或者是在排队等待操作系统给它分配 CPU 资源;原创 2020-11-25 11:34:18 · 263 阅读 · 0 评论 -
HashMap 底层实现原理是什么?JDK8 做了哪些优化?
在 JDK 1.7 中 HashMap 是以数组加链表的形式组成的,JDK 1.8 之后新增了红黑树的组成结构,当链表大于 8 并且容量大于 64 时,链表结构会转换成红黑树结构,它的组成结构如下图所示: 数组中的元素我们称之为哈希桶,它的定义如下: static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<原创 2020-11-25 10:37:46 · 90 阅读 · 0 评论 -
String的特点是什么?它有哪些重要方法?
以主流的 JDK 版本 1.8 来说,String 内部实际存储结构为 char 数组,源码如下: public final class String implements java.io.Serializable, Comparable<String>, CharSequence { // 用于存储字符串的值 private final char value[]; // 缓存字符串的 hash code private int hash; // Defa原创 2020-11-25 10:14:36 · 168 阅读 · 0 评论