面经
文章平均质量分 51
会new对象的Java工程师
佛祖保佑,永无bug
展开
-
【Java】之继承
Java中使用extends关键字,让我们在类和类之间建立联系。使用继承的好处:可以将多个类中重复的代码,抽象至父类中供子类使用。子类可以在父类上的基础上继续增强,使子类可以有自己独特的性质和功能。特点:在Java中,只支持单继承,不支持多继承,但支持多层继承。原创 2023-09-10 16:02:20 · 228 阅读 · 0 评论 -
进程与线程
程序是一组指令的集合,它描述了完成特定任务的步骤和操作。程序通常以源代码的形式编写,可以使用编程语言如C、Java、Python等来表示。程序本身是,它只是存储在存储介质(如硬盘)上的一段代码。进程是计算机系统中的实例。当一个程序被执行时,操作系统会为其创建一个独立的进程。线程是。一个进程可以包含多个线程,它们共享进程的内存空间和系统资源。线程是操作系统调度的基本单位,可以并发执行。原创 2023-07-28 17:39:08 · 205 阅读 · 0 评论 -
【并发编程】ThreadLocal
TreadLocalMap 使用 ThreadLocal 的弱引用作为 key,如果一个 ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被 GC 回收,这样就会导致ThreadLocalMap 中 key 为 null, 而 value 还存在着强引用,只有 thead 线程退出以后,value 的强引用链条才会断掉。最终的变量是放在了当前线程的ThreadLocalMap中 ,并不是存在 ThreadLocal 上,ThreadLocal 作为 key。原创 2023-07-28 00:49:46 · 514 阅读 · 0 评论 -
【并发编程】线程池
直到线程池中的线程数不大于 corePoolSize,即当线程池中的线程数大于 corePoolSize 时,如果一个线程空闲的时间达到 keepAliveTime,则会终止,直到线程池中的线程数不超过 corePoolSize。在创建了线程池后,默认情况下,在创建了线程池后,线程池中的线程数为 0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目。如果线程池中存活的核心线程数小于线程数 corePoolSize 时,线程池会创建一个核心线程去处理提交的任务。原创 2023-07-28 00:43:27 · 109 阅读 · 0 评论 -
ConcurrentHashMap
ConcurrentHashmap 和 Hashtable 都是支持并发的,这样会有一个问题,当你通过 get(k)获取对应的 value 时,如果获取到的是 null 时,你无法判断,它是 put(k,v)的时候 value 为 null,还是这个 key 从来没有做过映射。jdk8 放弃了分段锁而是用了 Node 锁,减低锁的粒度,提高性能,并使用 CAS 操作来确保 Node 的一些操作的原子性,取代了锁。里面是模糊不清的,所以压根就不让 put null。,分段锁反而会造成更新等操作的长时间等待。原创 2023-07-28 00:42:17 · 296 阅读 · 0 评论 -
ReentrantLock 锁实现
ReentrantLock 是 java.util.concurrent.locks 包下的类 , 实现 Lock 接口。NonfairSync 类继承了 Sync 类,表示采用非公平策略获取锁,其实现了 Sync 类中抽象的 lock 方法。FairSync 类也继承了 Sync 类,表示采用公平策略获取锁,其实现了 Sync 类中的抽象 lock 方法。来对共享资源进行同步,同时和 synchronized 一样,ReentrantLock。,除此之外,ReentrantLock 在调度上。原创 2023-07-25 15:07:33 · 115 阅读 · 0 评论 -
【并发编程】AQS
AQS 的全称为( AbstractQueuedSynchronizer ), 这个类在 java.util.concurrent.locks 包下面。AQS 是一个用来的框架,使用 AQS 能简单且高效地构造出同步器 , 是 JUC 中 核 心 的 组 件 ,比如我们提到的ReentrantLock,CountDownLatch 等等都是基于 AQS 来实现。只要搞懂了 AQS,那么 JUC 中绝大部分的 api 都能掌握。在内部有一个变量表示。原创 2023-07-25 15:02:32 · 111 阅读 · 0 评论 -
synchronized 锁实现
当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,该标记表明线程进入该方法时,需要 monitorenter,退出该方法时需要 monitorexit。,线程代码执行在进入 synchronized 代码块时候会自动获取内部锁,这个时候其他线程访问时候会被阻塞,直到进入 synchronized 中的代码执行完毕或者抛出异常或者调用了 wait 方法,都会释放锁资源。当前线程拥有了这个对象的锁,把锁的计数器+1;当计数器为 0 时,锁就被释放了。原创 2023-07-25 14:56:59 · 72 阅读 · 0 评论 -
Java 中的锁分类
乐观锁在 Java 中的使用,是无锁编程,常常采用的是 CAS 算法,典型的例子就是原子类,通过 CAS 自旋实现原子操作的更新。重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会。轻量级锁是指当锁是偏向锁的时候,此时又有一个线程访问,偏向锁就会升级为轻量级锁,其他线程会通过。由此可见,自旋锁是是比较消耗 CPU 的,因为要不断的循环重试,不会释放 CPU资源。读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。原创 2023-07-22 14:48:20 · 60 阅读 · 0 评论 -
【并发编程】CAS
如原先的内存值为(A,1),线程将(A,1)修改为了(B,2),再由(B,2)修改为(A,3)。此时另一个线程使用预期值(A,1)与内存值(A,3)进行比较, 只需要比较版本号 1 和 3,即可发现该内存中的数据被更新过了。每次判断我的预期值和内存中的值是不是相同,如果不相同则说明该内存值已经被其他线程更新过了,因此需要拿到该最新值作为预期值,重新判断。当另外一个线程使用预期值去判断时,预期值与内存值相同,当前线程的 CAS 操作无法分辨当前 V 值是否发生过变化。的一种实现方式,他采用的是。原创 2023-07-22 14:45:33 · 85 阅读 · 0 评论 -
原子性的实现
synchronized 一定能保证原子性,因为被 synchronized 修饰某段代码后,无论是单核 CPU 还是多核 CPU,只有一个线程能够执行该代码,所以一定能保证原子操作。也就是说,一个获得锁的线程被CPU切换走了,即使其他线程来访问这段临界资源,由于锁被占用,也无法访问。synchronized 来保证原子性。:进程只能一个一个的执行,同时有多个进程,那么根据一定的规则(调度算法)选取一个执行,其他先等待。,例如Java 语言提供的 synchronized 关键字,就是锁的一种实现。原创 2023-07-22 14:40:50 · 134 阅读 · 0 评论 -
Volatile关键字
被volatile修饰的共享变量,对其他线程是可见的。禁止指令重排。volatile不能保证对变量操作的原子性。volatile可以解决不可见性和无序性,但不能保证原子性。原创 2023-07-22 14:39:03 · 54 阅读 · 0 评论 -
【并发编程】安全问题
缓存导致的可见性问题,编译优化带来的有序性问题,线程切换带来的原子性问题,。其实缓存、线程、编译优化的目的和我们写并发程序的目的是相同的,都是提高程序安全性和性能。但是技术在解决一个问题的同时,必然会带来另外一个问题,所以在采用一项技术的同时,一定要清楚它带来的问题是什么,以及如何规避。原创 2023-07-21 18:23:05 · 51 阅读 · 0 评论 -
Java内存模型(JMM)
Java 虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为 Java 内存模型。这里的工作内存是 JMM 的一个抽象概念,也叫本地内存,其存储了该线程读 / 写共享变量的副本。,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。Java 内存模型(Java Memory Model,JMM)Java 内存模型中规定了所有的变量都存储在。原创 2023-07-21 18:21:46 · 59 阅读 · 0 评论 -
缓存穿透、缓存击穿、缓存雪崩
2.加锁:上面的现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后将数据放到 redis 缓存起来。前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取, 数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。,每次针对此 key 的请求从缓存获取不到, 请求都会到数据库,从而可能压垮数据库。,尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)。原创 2023-07-21 18:18:17 · 57 阅读 · 0 评论 -
【Redis】Key 过期策略
每隔一段时间执行一次删除操作,并通过限制删除操作执行的时长和频率,来减少删除操作对 cpu 的影响。另一方面定时删除也有效的减少了因惰性删除带来的内存浪费。:立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。redis 使用的过期键值删除策略是:惰性删除加上定期删除,两者配合使用。,当过期时间达到时,由时间处理器自动执行键的删除操作。,对 expires 字典进行检查,删除里面的过期键。,才会被检查到过期,此时才能得到删除。某个键值过期后,此键值。原创 2023-07-21 18:14:03 · 105 阅读 · 0 评论 -
【Redis】集群
由从节点提供读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。主从模式很好的解决了数据备份问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取数据的命令发送给不同的从机执行,从而达到。哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的。:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,原创 2023-07-20 22:00:53 · 61 阅读 · 0 评论 -
【Redis】 事务
Redis 事务本质是一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行。所有的命令在事务中,并没有直接被执行。只有发起执行 exec 命令的时候才会执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。命令观测监听某个键的变化,如果在其他客户端将监听值修改,在事务中对某个键操作时,事务会失效。同一事物中多条命令执行的原子性,即使命令有错误也会添。加到队列中,执行报错也不影响其他命令执行。在事务开启前还可以通过。开启事务(multi)执行事务(exec)原创 2023-07-20 21:54:40 · 57 阅读 · 0 评论 -
【程序、进程、线程】的区别与联系(全网最全面最清晰)
程序是一组指令的集合,它描述了完成特定任务的步骤和操作。程序通常以源代码的形式编写,可以使用编程语言如C、Java、Python等来表示。程序本身是静态的,它只是存储在存储介质(如硬盘)上的一段代码。进程是计算机系统中正在运行的程序的实例。当一个程序被执行时,操作系统会为其创建一个独立的进程。线程是进程中的执行单元。一个进程可以包含多个线程,它们共享进程的内存空间和系统资源。线程是操作系统调度的基本单位,可以并发执行。原创 2023-07-13 19:32:17 · 899 阅读 · 0 评论