![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
java基础
文章平均质量分 65
其实系一个须刨
这个作者很懒,什么都没留下…
展开
-
@Transactional注解的失效场景
1. @Transactional 应用在非 public 修饰的方法上2. @Transactional 注解属性 propagation 设置错误这种失效是由于配置错误,若是错误的配置以下三种 propagation,事务将不会发生回滚。TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。TransactionDefinition.PROPAGATION_NOT_SUPPORTE原创 2021-07-11 23:16:30 · 493 阅读 · 0 评论 -
ConcurrentHashMap原理
ConcurrentHashMap采用了非常精妙的"分段锁"策略,ConcurrentHashMap的主干是个Segment数组。static class Segment<K,V> extends ReentrantLock implements Serializablefinal Segment<K,V>[] segments; Segment继承了ReentrantLock,所以它就是一种可重入锁(ReentrantLock)。在Concurren...原创 2021-07-10 21:36:05 · 293 阅读 · 1 评论 -
hashmap原理
loadFactor:数据的增长因子,默认为0.75。在进行扩容操作会使用到。 threshold:允许的最大的存储的元素数量,通过length数组长度*loadFactor增长因子得出 modCount:记录内部结构发生变化的次数,put操作(覆盖值不计算)以及其他... size:实际存储的元素数量put方法final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boole...原创 2021-07-10 18:01:17 · 226 阅读 · 0 评论 -
简单实现一个lock
import java.lang.reflect.Field;import java.util.concurrent.ConcurrentLinkedQueue;import java.util.concurrent.locks.LockSupport;import sun.misc.Unsafe;public class MyLock { private static Unsafe unsafe; /** * 当前加锁状态,记录加锁的次数 */ .原创 2021-07-09 20:17:20 · 178 阅读 · 0 评论 -
CopyOnWriteArrayList
CopyOnWriteArrayList是ArrayList的线程安全版本,CopyOnWriteArrayList是在有写操作的时候会copy一份数据,然后写完再设置成新的数据。CopyOnWriteArrayList适用于读多写少的并发场景,CopyOnWriteArraySet是线程安全版本的Set实现,它的内部通过一个CopyOnWriteArrayList来代理读写等操作,使得CopyOnWriteArraySet表现出了和CopyOnWriteArrayList一致的并发行为,他...原创 2021-07-08 21:29:09 · 401 阅读 · 0 评论 -
三次握手过程中有哪些不安全性
SYN洪泛攻击服务器处于SYN_Wait的状态: 1)伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送。当大量的攻击者请求建立连接时,服务器就会存在大量未完成三次握手的连接,服务器主机backlog被耗尽而不能响应其它连接。即SYN泛洪攻击(属于DOS的一种,发送大量的半连接请求,耗费CPU和内存资源,引起网络堵塞甚至系统瘫痪) 当你在服务器上看到大量的...原创 2021-07-06 16:03:37 · 625 阅读 · 0 评论 -
解决TIME_WAIT过多造成的问题
看到TIME_WAIT状态是在tcp断开链接时产生的,因为TCP连接是双向的,所以在关闭连接的时候,两个方向各自都需要关闭。先发FIN包的一方执行的是主动关闭;后发FIN包的一方执行的是被动关闭。主动关闭的一方会进入TIME_WAIT状态,并且在此状态停留两倍的MSL时长。 MSL指的是报文段的最大生存时间,如果报文段在网络活动了MSL时间,还没有被接收,那么会被丢弃。关于MSL的大小,RFC 7...原创 2021-07-05 21:18:05 · 5539 阅读 · 1 评论 -
设计模式(十二):代理模式,动态代理与静态代理
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。优点:1、职责清晰。 2、高扩展性。 3、智能化。缺点:1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。例子:如果你想找个歌星出台唱歌,你不直接和歌星接触,而是先找...原创 2020-02-16 22:17:27 · 70 阅读 · 0 评论 -
a=a+b与a+=b有什么区别
+=操作符会进行隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换。如:byte a = 127;byte b = 127;b = a + b; // error : cannot convert from int to byteb += a; // ok(其实无论 a+b 的值为多少,编译器都会报错,因为 a+b 操作会将 a、b 提升为 int 类型,所以将 int 类型赋值给 byte 就会编译出错)...原创 2021-07-02 00:40:59 · 237 阅读 · 0 评论 -
面向对象五大基本原则
单一职责原则SRP(Single Responsibility Principle) 类的功能要单一,不能包罗万象,跟杂货铺似的。 开放封闭原则OCP(Open-Close Principle) 一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。 里式替换原则LSP(the Liskov Substitution Principle LSP) 子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~ ..原创 2021-07-02 00:29:46 · 93 阅读 · 0 评论 -
TCP三次握手/四次挥手
三次握手第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack ...原创 2021-06-29 22:06:05 · 89 阅读 · 0 评论 -
什么是 AQS(抽象的队列同步器)
AbstractQueuedSynchronizer类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch。它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。这里volatile是核心关键词。state的访问方式有三种: getState() setSta...原创 2021-06-28 22:58:51 · 291 阅读 · 0 评论 -
线程上下文切换
上下文 是指某一时间点 CPU 寄存器和程序计数器的内容。引起线程上下文切换的原因1. 当前执行任务的时间片用完之后,系统CPU正常调度下一个任务;2. 当前执行任务碰到IO阻塞,调度器将此任务挂起,继续下一任务;3. 多个任务抢占锁资源,当前任务没有抢到锁资源,被调度器挂起,继续下一任务;4. 用户代码挂起当前任务,让出CPU时间;5. 硬件中断;...原创 2021-06-28 22:43:19 · 76 阅读 · 0 评论 -
JAVA中的各种锁
乐观锁乐观锁认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。 java中的乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。悲观锁悲观锁认为写多,遇到并发写的可能性高,每次去拿数据的时候...原创 2021-06-28 22:37:30 · 308 阅读 · 0 评论 -
sleep与wait 区别
1. 对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。2. sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。3. 在调用sleep()方法的过程中,线程不会释放对象锁。4. 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。原创 2021-06-28 22:04:25 · 61 阅读 · 0 评论 -
线程池基本概念
通过Executors线程池工具类来使用:Executors.newSingleThreadExecutor():创建只有一个线程的线程池 Executors.newFixedThreadPool(int):创建固定线程的线程池 newScheduledThreadPool 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。 Executors.newCachedThreadPool():创建一个可缓存的线程池,线程数量随着处理业务数量变化。使用Executors.newCachedT原创 2021-06-28 21:54:29 · 55 阅读 · 0 评论 -
JAVA IO模型/NIO
阻塞IO模型最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。典型的阻塞IO模型的例子为:data = socket.read();如果数据没有就绪,就会一直阻塞在read方法。非阻塞IO模型当用户线程发起一个read操作后,并不需要等待...原创 2021-06-28 10:36:57 · 68 阅读 · 0 评论 -
JVM内存模型
JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA堆、方法区】、直接内存。程序计数器(线程私有) 一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。 正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是Native方法,则为空。 这个内存区域是唯一一个在虚拟机中没...原创 2021-06-26 00:38:55 · 75 阅读 · 1 评论 -
进程、线程之间的通信方式
一、进程间的通信方式管道( pipe ) 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 调用pipe函数,会在内核中开辟出一块缓冲区用来进行进程间通信,这块缓冲区称为管道,它有一个读端和一个写端。pipe函数接受一个参数,是包含两个整数的数组,如果调用成功,会通过pipefd[2]传出给用户程序两个文件描述符,需要注意pipefd[0]指向管道的读端, pipefd [1]指向管道的写端,那么此时这个管...原创 2021-06-24 11:32:31 · 1694 阅读 · 0 评论 -
ConCurrentHashMap在jdk1.8与1.7的变化
主要改变为:去除 Segment + HashEntry + Unsafe 的实现,改为 Synchronized + CAS + Node + Unsafe 的实现。Node 和 HashEntry 的内容一样,但是HashEntry是一个内部类。 用 Synchronized + CAS 代替 Segment ,这样锁的粒度更小了,并且不是每次都要加锁了,CAS尝试失败了在加锁。 put()方法中 初始化数组大小时,1.8不用加锁,将sizeCtl 这个变量置为-1,就表明table正在初始..原创 2021-06-24 19:15:57 · 264 阅读 · 0 评论 -
ThreadLocal介绍
什么是ThreadLocal? ThreadLocal类顾名思义可以理解为线程本地变量。也就是说如果定义了一个ThreadLocal,每个线程往这个ThreadLocal中读写是线程隔离,互相之间不会影响的。它提供了一种将可变数据通过每个线程有自己的独立副本从而实现线程封闭的机制。它大致的实现思路是怎样的? Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalM...原创 2021-06-23 15:54:56 · 1481 阅读 · 0 评论 -
ArrayList和LinkedList
ArrayList和LinkedList在性能上各有优缺点,都有各自所适用的地方,总的说来可以描述如下:1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入.原创 2021-06-23 10:26:37 · 49 阅读 · 0 评论 -
synchronized原理
1,JDK1.6之前synchronized是由一对monitor-enter和monitor-exit指令实现的。这对指令的实现是依靠操作系统内部的互斥锁来实现的,期间会涉及到用户态到内存态的切换,所以这个操作是一个重量级的操作,性能较低。2,JDK1.6之后JVM对synchronized进行了优化,改了三个经历的过程偏向锁-》轻量级锁-》重量级锁偏向锁:在锁对象保存一个thread-id字段,刚开始初始化为空,当第一次线程访问时,则将thread-id设置为当前线程id,此原创 2021-06-15 15:21:19 · 132 阅读 · 1 评论 -
谈谈Sleep和wait的区别
1,所属的类不同:sleep方法是定义在Thread上wait方法是定义在Object上2,对于锁资源的处理方式不同sleep不会释放锁wait会释放锁3,使用范围:sleep可以使用在任何代码块wait必须在同步方法或同步代码块执行4,与wait配套使用的方法void notify()Wakes up a single thread that is waiting on this object’s monitor.译:唤醒在此对象监视器上等待的单个线程void n原创 2021-06-15 15:00:37 · 118 阅读 · 0 评论 -
LinkedHashMap和HashMap的区别
主要关注几个点:1,初始化大小是16,如果事先知道数据量的大小,建议修改默认初始化大小。 减少扩容次数,提高性能 ,这是我一直会强调的点2,最大的装载因子默认是0.75,当HashMap中元素个数达到容量的0.75时,就会扩容。 容量是原先的两倍3,HashMap底层采用链表法来解决冲突。 但是存在一个问题,就是链表也可能会过长,影响性能于是JDK1.8,对HashMap做了进一步的优化,引入了红黑树。当链表长度超过8,且数组容量大于64时,链表就会转换为红黑树当红黑树的节点数量小于6时,会将原创 2021-06-15 11:40:34 · 140 阅读 · 0 评论 -
接口与抽象类的区别
相同点(1)都不能被实例化 (2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。不同点(1)接口只有定义,不能有方法的实现,java 1.8中可以定义default方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。(2)实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。(3)接口强调特定功能的实现,而抽象类强调所属关系。(4)接口成...原创 2021-06-15 11:32:28 · 1098 阅读 · 1 评论 -
Java 对象的创建过程
1.实例变量初始化与实例代码块初始化我们在定义(声明)实例变量的同时,还可以直接对实例变量进行赋值或者使用实例代码块对其进行赋值。如果我们以这两种方式为实例变量进行初始化,那么它们将在构造函数执行之前完成这些初始化操作。实际上,如果我们对实例变量直接赋值或者使用实例代码块赋值,那么编译器会将其中的代码放到类的构造函数中去,并且这些代码会被放在对超类构造函数的调用语句之后(还记得吗?Java要求构造函数的第一条语句必须是超类构造函数的调用语句),构造函数本身的代码之前。...原创 2021-05-31 21:01:40 · 100 阅读 · 0 评论 -
java对象实例化顺序
静态成员变量 静态代码块 成员变量 方法块 构造函数 的加载顺序Java程序在执行过程中,类,对象以及它们成员加载、初始化的顺序如下:1、首先加载要创建对象的类及其直接与间接父类。2、在类被加载的同时会将静态成员进行加载,主要包括静态成员变量的初始化,静态语句块的执行,在加载时按代码的先后顺序进行。3、需要的类加载完成后,开始创建对象,首先会加载非静态的成员,主要包括非静态成员变量的初始化,非静态语句块的执行,在加载时按代码的先后顺序进行。4、最后执行构造器,构造器执行完毕,对象生成。...原创 2021-05-29 16:50:28 · 194 阅读 · 0 评论 -
java的volatile机制
由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。这样子当两个线程同时对一个变量修改,如i++,可能就会出现缓存不一致的问题。缓存一致性协议:原创 2021-05-28 19:59:04 · 73 阅读 · 0 评论 -
Java中Math.round(-1.5)
Math.round(-1.5)的返回值是-1。四舍五入的原理是在参数上加0.5然后做向下取整。System.out.println(Math.round(-1.5)); //-1System.out.println(Math.round(-1.6)); //-2原创 2021-05-27 15:50:25 · 164 阅读 · 0 评论 -
Java中equals和==的区别
java当中的数据类型和“==”的含义:基本数据类型(也称原始数据类型) :byte,short,char,int,long,float,double,boolean。他们之间的比较,应用双等号(==),比较的是他们的值。 引用数据类型:当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。注:对于第二种类型,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。因为每new一次,都会重新开辟堆内存空间。equals().原创 2021-05-27 15:11:13 · 69 阅读 · 0 评论 -
G1垃圾回收器
G1回收器和CMS比起来,有以下不同:G1垃圾回收器是compacting的,因此其回收得到的空间是连续的。这避免了CMS回收器因为不连续空间所造成的问题。如需要更大的堆空间,更多的floating garbage。连续空间意味着G1垃圾回收器可以不必采用空闲链表的内存分配方式,而可以直接采用bump-the-pointer的方式; G1回收器的内存与CMS回收器要求的内存模型有极大的不同。G1将内存划分一个个固定大小的region,每个region可以是年轻代、老年代的一个。内存的回收是以regio原创 2021-05-26 21:38:29 · 396 阅读 · 0 评论 -
JVM 内存区域
程序计数器(PC,Program Counter Register)。在 JVM 规范中,每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址;或者,如果是在执行本地方法,则是未指定值(undefined)。Java 虚拟机栈(Java Virtual Machine Stack),早期也叫 Java 栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame)原创 2021-05-26 19:56:32 · 49 阅读 · 0 评论 -
线程概念
Java 的线程是不允许启动(start)两次的,第二次调用必然会抛出 IllegalThreadStateException,这是一种运行时异常,多次调用 start 被认为是编程错误。关于线程生命周期的不同状态,在 Java 5 以后,线程状态被明确定义在其公共内部枚举类型 java.lang.Thread.State 中,分别是:新建(NEW),表示线程被创建出来还没真正启动的状态,可以认为它是个 Java 内部状态。 就绪(RUNNABLE),表示该线程已经在 JVM 中执行,..原创 2021-05-25 21:35:55 · 62 阅读 · 0 评论 -
synchronized和ReentrantLock
线程安全是一个多线程环境下正确性的概念,也就是保证多线程环境下共享的、可修改的状态的正确性,这里的状态反映在程序中其实可以看作是数据。线程安全需要保证几个基本特性:原子性,简单说就是相关操作不会中途被其他线程干扰,一般通过同步机制实现。 可见性,是一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线程本地状态反映到主内存上,volatile 就是负责保证可见性的。 有序性,是保证线程内串行语义,避免指令重排等。.ReentrantLock可重入锁表示当一个线程试.原创 2021-05-25 19:46:48 · 92 阅读 · 0 评论 -
接口和抽象类
接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到 API 定义和实现分离的目的。接口,不能实例化;不能包含任何非常量成员,任何 field 都是隐含着 public static final 的意义;同时,没有非静态方法实现,也就是说要么是抽象方法,要么是静态方法。抽象类是不能实例化的类,用 abstract 关键字修饰 class,其目的主要是代码重用。除了不能实例化,形式上和一般的 Java 类并没有太大区别,可以有一个或者多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关 Java原创 2021-05-25 16:00:50 · 65 阅读 · 0 评论 -
IO方式
用户态空间(User Space)和内核态空间(Kernel Space),这是操作系统层面的基本概念,操作系统内核、硬件驱动等运行在内核态空间,具有相对高的特权;而用户态空间,则是给普通应用和服务使用。 当我们使用输入输出流进行读写时,实际上是进行了多次上下文切换,比如应用读取数据时,先在内核态将数据从磁盘读取到内核缓存,再切换到用户态将数据从内核缓存读取到用户缓存。基于 NIO transferTo 的实现方式,在 Linux 和 Unix 上,则会使用到零...原创 2021-05-25 11:29:54 · 204 阅读 · 0 评论 -
Java的IO操作
首先看两个概念区分同步或异步(synchronous/asynchronous)。同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下一步;而异步则相反,其他任务不需要等待当前调用返回,通常依靠事件、回调等机制来实现任务间次序关系。 区分阻塞与非阻塞(blocking/non-blocking)。在进行阻塞操作时,当前线程会处于阻塞状态,无法从事其他任务,只有当条件就绪才能继续,比如 ServerSocket 新连接建立完毕,或数据读取、写入操作完成;而非阻塞则原创 2021-05-24 22:48:49 · 109 阅读 · 2 评论 -
ConcurrentHashMap分析
早期 ConcurrentHashMap,其实现是基于:分离锁,也就是将内部进行分段(Segment),里面则是 HashEntry 的数组,和 HashMap 类似,哈希相同的条目也是以链表形式存放。 HashEntry 内部使用 volatile 的 value 字段来保证可见性,也利用了不可变对象的机制以改进利用 Unsafe 提供的底层能力,比如 volatile access,去直接完成部分操作,以最优化性能,毕竟 Unsafe 中的很多操作都是 JVM intrinsic 优化过的。在进原创 2021-05-24 22:22:25 · 290 阅读 · 1 评论 -
Hashtable、HashMap、TreeMap
Hashtable 是早期 Java 类库提供的一个哈希表实现,本身是同步的,不支持 null 键和值,由于同步导致的性能开销,所以已经很少被推荐使用。 HashMap 是应用更加广泛的哈希表实现,行为上大致上与 HashTable 一致,主要区别在于 HashMap 不是同步的,支持 null 键和值等。通常情况下,HashMap 进行 put 或者 get 操作,可以达到常数时间的性能。 TreeMap 则是基于红黑树的一种提供顺序访问的 Map,和 HashMap 不同,它的 get、put、re原创 2021-05-24 21:43:33 · 209 阅读 · 0 评论