![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
java基本知识
虎哥和你一起学编程
路漫漫其修远兮吾将上下而求索
展开
-
java集合中的fail-fast与fail-safe两种模式
线程不安全的集合在获取迭代器迭代的时候,如果集合中的元素发生了变化,例如新增或者删除,由于线程不安全,迭代器在next时会直接抛出concurrentModificationException,通过内部的一个modCount判断是否等于expectedModCount来进行比较。可以看到j.u.c包下的线程安全的集合在迭代的过程中,如果集合的元素发生了修改,并不会抛异常,这就是fail-safe机制,但是缺点就是元素的修改并不会立刻反映出来,适用于读多写少的场景。fail-safe案例。原创 2022-11-14 11:18:19 · 304 阅读 · 0 评论 -
guava LoadingCache
guava中提供了LoadingCache本地缓存,可以很方便的使用本地缓存。 eg:public class TestCache { public static void main(String[] args) throws ExecutionException { LoadingCache<Integer, String> cache = CacheBuilder.newBuilder().expireAfterAccess(...原创 2022-02-17 17:42:42 · 305 阅读 · 0 评论 -
找到最接近的2的n次方
public class Test { public static void main(String[] args) { System.out.println(ceilingPowerOfTwo(1)); System.out.println(ceilingPowerOfTwo(3)); System.out.println(ceilingPowerOfTwo(5)); System.out.println(ceilingPower.原创 2022-02-14 17:13:00 · 630 阅读 · 0 评论 -
线程池中的任务抛异常了会怎么样
线程池可以通过execute和submit两种方式来提交任务。先看使用execute方式提交任务 /** * Main worker run loop. Repeatedly gets tasks from queue and * executes them, while coping with a number of issues: * * 1. We may start out with an initial task, in whic...原创 2022-01-18 10:32:18 · 203 阅读 · 0 评论 -
stream分组求和
如何用Streamapi进行分组求和,可以使用Collectors.groupby(**, Collectors.summingInt(**))来进行分组求和。 public class Test { public static void main(String[] args) { Student student1 = new Student(1, 1); Student student2 = new Student(1, 1); ...原创 2022-01-17 21:19:50 · 15749 阅读 · 0 评论 -
java序列化的缺点
基于java提供的对象输入/输出流(ObjectInputStream/ObjectOutputStream),可以直接把Java对象作为可存储的字节数组写入文件,也可以传输到网络上。对程序员来说,基于JDK默认的序列化机制可以避免操作底层的字节数组,从而提升开发效率。 Java序列化的目的主要有两个: 1.网络传输 2.对象持久化 当进行远程跨进程服务调用时,需要把被传输的Java对象编码为字节数组或者ByteBuffer对象。而当远程服务读取到ByteBuffer对象或者...原创 2021-12-03 10:17:06 · 910 阅读 · 0 评论 -
两个线程交替打印1-10
AtomicInteger num = new AtomicInteger(1); Object lock = new Object(); Thread t1 = new Thread(() -> { synchronized(lock){ while(num.get() <= 10){ if(num.get() % 2 == 1){ .原创 2021-10-13 19:39:03 · 363 阅读 · 0 评论 -
CompletionService讲解
CompletionService的源码注释package java.util.concurrent;/** * A service that decouples the production of new asynchronous tasks * from the consumption of the results of completed tasks. Producers * {@code submit} tasks for execution. Consumers ...原创 2021-08-31 05:07:53 · 145 阅读 · 0 评论 -
String为什么是不可变的
Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. 不可变所以可以共享,线程安全两个好处。因为字符串是最基础的类,会大量重复,所以才设计成不可变的。...原创 2021-07-30 14:55:40 · 108 阅读 · 0 评论 -
ArrayBlockingQueue与LinkedBlockingQueue的对比
ArrayBlockingQueue 有界 基于数组 公平/非公平 单锁 LinkedBlockingQueue 无界 基于单链表 分公平 锁分离/双锁 LinkedBlockingQueue通过锁分离实现了放入和取出的不互斥,从而可以拥有更大的吞吐量。...原创 2021-07-16 11:36:04 · 193 阅读 · 0 评论 -
java使用CRC32计算校验和
校验和checkSum指的是通过一定的算法,将一个文件流转换为一串字母或数字,当文件流发生变化时,得到的校验和也会不同。 通常用来判断一个文件是否有修改及远距离传输时判断文件的完整性。 eg:Java使用CRC32的示例:public static String getFileCRCCode(String path) throws Exception { File file = new File(path); FileInpu...原创 2021-07-05 09:45:10 · 2480 阅读 · 0 评论 -
java中的线程几种状态
/** * A thread state. A thread can be in one of the following states: * <ul> * <li>{@link #NEW}<br> * A thread that has not yet started is in this state. * </li> * <li>{@link #RUNNABLE}&.原创 2021-06-29 20:53:23 · 53 阅读 · 0 评论 -
线程池的corepoolsize设置为多少
线程池的设置要看任务的类型,一般分为IO密集型和计算密集型 针对计算密集型的任务,一般设置为 N(cpu核心数)+ 1, 加一的目的是因为cpu可能会出现内存页缺失或任务异常时可以最大限度的发挥多核cpu的优势。 IO密集型的一般设置为 2N(cpu核心数) + 1 或者还可以有另外一个公式 N(cpu核心数) / 1 - 阻塞系数 在IO密集型任务中,一般阻塞系数取0.8 ~0.9...原创 2021-06-29 20:29:07 · 3068 阅读 · 0 评论 -
StampedLock
jdk中提供了ReadWriteLock来实现读写锁,从而实现了读读不互斥,读写互斥,但是说到底还是一种悲观锁的形式,因为读的时候不允许写。 jdk中还提供了一种乐观锁的读写锁StampedLock。乐观读不加锁,但是要有一种机制检测是否当前有写线程正在写入。 源码中示例: * <pre>{@code * class Point { * private double x, y; * private fin...原创 2021-06-29 17:19:33 · 44 阅读 · 0 评论 -
基于LockSupport实现FIFO队列
LockSupport类中包含有实现FIFO队列的例子,可以借鉴。 public class FIFOMutext { private AtomicBoolean locked = new AtomicBoolean(false); private Queue<Thread> waiter = new ConcurrentLinkedQueue<>(); public void lock(){ b...原创 2021-06-28 17:18:18 · 94 阅读 · 0 评论 -
G1垃圾收集器与CMS垃圾收集器
CMS垃圾收集器整体上是采用标记-清除算法,而G1垃圾收集器整体上是采用标记-整理算法,可以避免内存碎片的产生。 另外G1(Garbage First) 将整个堆分为多个region(区域),通过维护一个每个区域的垃圾的队列,从而每次收集效益最大的区域,从而实现了可预测的stop the world的时间。...原创 2021-06-27 15:03:09 · 93 阅读 · 0 评论 -
Condition与Object monitor的区别
Lock类似于Synchronized condition类似于Object monitor await/signal类似于wait/notify方法,区别如下:{@code Condition} factors out the {@code Object} monitor * methods ({@link Object#wait() wait}, {@link Object#notify notify} * and {@link Object#notify...原创 2021-06-25 16:15:32 · 241 阅读 · 0 评论 -
ReentrantLock的公平锁与非公平锁
ReentrantLock类中包含FairLock和NonfairLock两个内部类继承Sync,实现了公平锁和非公平锁的方法。它们在获取不到锁时都会加入FIFO队列排队等待,唯一不同的是新来一个线程要来获取锁时,公平锁会判断队列头部是否有在等待的线程。 NonfairLock /** * Performs non-fair tryLock. tryAcquire is implemented in * subclass...原创 2021-06-21 17:59:52 · 300 阅读 · 0 评论 -
类加载器死锁问题
类加载器在加载类时会加锁,当循环加载类时就可能会导致死锁问题,如下示例:public class TestDeadLock { static class A { static { System.out.println("cinit A"); try { TimeUnit.SECONDS.sleep(1); }catch (InterruptedExcepti...原创 2021-06-16 20:00:44 · 379 阅读 · 0 评论 -
BitSet在Spring中的使用
BitSet在Spring中用于判断是否有非法字符。 在MimeType类中原创 2021-06-10 14:45:14 · 132 阅读 · 0 评论 -
使用synchronized实现Lock接口的lock和unlock方法
public class TestLock implements Lock { private Object lock = new Object(); private long owner = -1; @Override public void lock() { while(owner != -1){ System.out.println(Thread.currentThread().getId() + "等待锁");...原创 2021-06-09 17:51:20 · 365 阅读 · 0 评论 -
泛型擦除示例
java中的泛型都是伪泛型,在编译器会进行泛型擦除。例如以下例子 public static void main(String[] args) { Class a = new ArrayList<Integer>().getClass(); Class b = new ArrayList<String>().getClass(); System.out.println(a == b); } 最后输出t...原创 2021-06-09 14:38:46 · 104 阅读 · 0 评论 -
LongAdder原理
在阿里巴巴编码规范中,在高并发情况下,LongAdder的效率比AtomicLong要高,因为减少了AtomicLongkong zi xuan原创 2021-05-31 17:33:24 · 164 阅读 · 0 评论 -
CAS的ABA问题
cas可能会导致ABA的问题,jdk中提供了AtomicMarkableReference和AtomicStampleReference两个l原创 2021-05-31 10:54:44 · 67 阅读 · 0 评论 -
synchronized锁优化
synchronized在jdk1.6后进行了优化,存在无锁-->偏向锁-->轻量级锁-->重量级锁的一个过程。 1.对象初始创建时会处于无锁的状态。 2.当某一个线程来获取对象锁时,升级为偏向锁。 3.当另外一个线程来获取对象锁时,尝试通过cas来替换对象头的线程id,如果替换成功,那么偏向锁偏向当前线程,如果替换失败, 那么偏向锁升级成为轻量级锁,通过cas自旋操作来等待锁。 ...原创 2021-05-27 11:31:52 · 257 阅读 · 0 评论 -
ThreadPoolExecutor的钩子方法
ThreadPoolExecutor提供了三个钩子方法,可以在任务执行前后或者终止时做一些额外的操作。 /* Extension hooks */ /** * Method invoked prior to executing the given Runnable in the * given thread. This method is invoked by thread {@code t} that * will ex...原创 2021-05-25 15:18:20 · 490 阅读 · 0 评论 -
Callable接口原理解析
Thread类通过Runnable target可以接收一个Runnable接口的实现来处理,但是Runnable接口没有返回值,如果需要异步执行的返回值就需要使用Callable接口。 Callable接口的实现依赖于RunnableFuture这个类,它是一个接口。 public interface RunnableFuture<V> extends Runnable, Future<V> { /** * Se...原创 2021-05-25 11:59:36 · 182 阅读 · 0 评论 -
Collections.synchronizedMap源码剖析
通常我们可以使用Collections.synchronizedMap来包装一下map,变成一个线程安全的map.它其实只是将map加上了一把互斥锁,达到了串行访问的效果,性能并不好,类似于Hashtable. /** * Returns a synchronized (thread-safe) map backed by the specified * map. In order to guarantee serial access, it ...原创 2021-05-22 09:49:47 · 553 阅读 · 0 评论 -
jdk动态代理的实现原理
先写一个jdk动态代理的例子 1.先定义一个接口 public interface MyService { void print();} 2.定义一个实现类public class MyServiceImpl implements MyService{ @Override public void print() { System.out.println("原始方法"); ...原创 2021-05-21 17:44:08 · 150 阅读 · 0 评论 -
短信登陆功能
通常我们在实现短信登陆时,需要给用户手机发送验证码,并且还有一个有效期,这个功能可以通过发送短信验证码时,将短信验证码存放在redis中,并且设置一个有效期来进行校验。原创 2021-05-20 15:41:13 · 146 阅读 · 0 评论 -
tomcat线程池与原生线程池的比较
jdk提供的线程池,当核心线程数已满,但是最大线程池数未满,来一个任务时,会先将任务加入阻塞队列。队列满之后才会创建线程来处理任务,这是比较适合cpu密集型任务的,但是像tomcat这种服务器程序就不太适合这种执行流程了。tomcat需要用户请求到达时马上就创建线程来处理,而不是加入阻塞队列。 先看看jdk原生线程池的执行流程。 public void execute(Runnable command) { if (co...原创 2021-05-17 10:38:28 · 523 阅读 · 0 评论 -
Threadlocal在线程池场景下如何传值
我们使用InheritableThreadLocal可以保证在子线程中拿到父线程设置的ThreadLocal的值,它在创建子线程时通过复制父线程的ThreadLocal的值来保证ThreadLocal的值的传递。但是在线程池这种线程复用的场景下,不会每次都创建线程。这就导致了ThreadLocal的值传递不起作用。例如如下例子: static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecuto...原创 2021-05-17 10:28:10 · 878 阅读 · 1 评论 -
集合类中的modcount属性
经常看jdk源码的同学应该发现在很多的集合类里面会有一个modcount的成员变量。这个变量的含义在AbstractList类中有详细的描述。 /** * The number of times this list has been <i>structurally modified</i>. * Structural modifications are those that change the size of the ...原创 2021-05-14 16:55:21 · 226 阅读 · 0 评论 -
HashMap之resize方法
hashmap的resize方法在初始化或者扩容的时候会调用。主要包含扩容(扩大容量capacity和threshold)及迁移元素两个过程。 迁移元素时,是先分裂链表或者红黑树,然后批量迁移。 /** * Initializes or doubles table size. If null, allocates in * accord with initial capacity target held in field ...原创 2021-05-14 16:51:34 · 1846 阅读 · 0 评论 -
软引用配合软引用队列使用
软饮用,弱引用一般可以实现内存敏感型缓存。当软引用指向的对象被回收时,会将软饮用加入引用队列。 /** * 设置最大堆内存. -Xmx20m */public class Test { static final int _4M = 4 * 1024 * 1024; public static void main(String[] args) throws InterruptedException { List<Sof...原创 2021-05-14 11:26:16 · 254 阅读 · 0 评论 -
happens before
由于cpu缓存和jvm指令重排序,导致在多线程并发时,可能导致并发问题。为了保证一致性提出了可以理解的happens before原则。 具体如下: 程序顺序规则:一个线程中的每一个操作,happens-before于该线程中的任意后续操作。 监视器规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。 volatile规则:对一个volatile变量的写,happens-before于任意后续对一个volatile变量的读。 传递性...原创 2021-05-14 10:21:03 · 79 阅读 · 0 评论 -
java垃圾回收器
垃圾收集器从简单意义上来说有四种 1.Serial:串行收集器,包含Serail new 和Serial old两种,使用单个线程来进行垃圾回收,适合单核CPU或者堆内存不大的情况。在垃圾回收时,GC线程与用户线程不可同时工作。 2.Parallel:并行收集器,包含ParNew,ParScanvage, ParOld三种收集器。使用多个线程并行来进行垃圾回收,适合多核CPU。在垃圾回收时,GC线程与用户线程不可同时工作。 3.C...原创 2021-05-13 16:36:38 · 189 阅读 · 0 评论 -
java里面的retry
java里面有一种类似于goto的用户 例如线程池的源码里面 private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue emp...原创 2021-05-10 20:23:01 · 181 阅读 · 0 评论 -
Class.forName与ClassLoader.loadClass的区别
Class.forName和ClassLoader.loadClass都可以加载一个类的信息,不同的是Class.forName会在加载类的信息时外加一个初始化的过程,会执行静态代码块和给静态变量赋初始值。 看一下Class.forName的源码 /** * Returns the {@code Class} object associated with the class or * interface with the given ...原创 2021-05-08 11:36:25 · 204 阅读 · 0 评论 -
raft原理动画演示网站
raft作为分布式一致性算法中较为简单的实现,但是只是通过文字来学习还是非常的枯燥难懂,这里分享一个动画演示raft的网站,可以帮助我们来理解raft. https://thesecretlivesofdata.com/raft/...原创 2021-05-07 15:21:35 · 352 阅读 · 0 评论