`
Rss 文章列表
AtomicInteger 是如何实现原子操作的了? 答案是 CAS(compare and swap) CAS是 Java Unsafe 类中实现的一些 native 方法,底层代码使用 c/c++ 编写,java 通过 jni 进行调用,在底层芯片级别保证原子操作的进行. 举个例子:假设有两个线程执行 i++ 语句,初始时 i = 0. 那么最终的输出结果可能不为 2. 因为 Java 内存模型的缘故,导致一个线程的修改还没有更新到主存中,另一个线程也进行了修改,最终的结果可能是 1.
简介: 就是一个 put 操作必须和 take 操作对应. 如果一下来了三个 put 操作,那么结果是这样的: head->put1->put2->put3. put1/put2/put3 都自旋一小会,如果还没有 take 来的话,就都调用 LockSupport.part 自我阻塞. 实现原理: 基于队列的实现原理: 还是上面的那个例子,假设一次性来了三个 put 操作,那么结果是这样的: head->put1->put2->put3. 现在假设来了一个 take 操作,那么对首出队,唤醒第一个节点的线程. put1 这个操作就能够继续执行了. 数据结构: ...
简介: LinkedBlockingDeque 是一个双端队列,在队列的两头都能进行 put/offer 操作.我感觉这个类很鸡肋,效率不是很高,大而全. 实现原理: LinkedBlockingDeque 底层使用一把锁(ReentrantLock)来控制入队出队操作.也就是说队列两头的操作来抢这一把锁. 所以这是我认为效率低下的原因. 使用场景: LinkedBlockingDeque 使用在工作窃取模式下. 工作窃取模式:比如说有两个工人A和B,A和B关系很好,老板给A和B分配了任务. 由于A的任务复杂度较低,先做完了,B 还在做. 因为A和B是好哥们,A说,哥们,你从前面往后做,我(A) ...
简介: 写操作时上锁,然后拷贝一个新的数组,操作新数组,将当前数组的引用设置为 array,释放锁. 思想: 采用读写分离的思想。读是一个数组,写是一个新的数组。这样做的优点是对读操作就可以不用上锁访问了,缺点是不能保证数据实时一致性,只能保证数据最终一致。 其他方面的内容和 ArrayList 差不多,唯一的区别就在于 CopyOnWriteArrayList 在进行写操作的时候上锁了.
简介: CyclicBarrier 实现这么一个功能,比如说吃饭,是不是要等所有人到齐了才能开始吃?CyclicBarrier 就实现了这么一个功能. 所有的线程都互相等待着,等所有的线程到达后,然后执行. CyclicBarrier 还可以实现这么一个功能,当所有人(线程)到齐后,可以先叫服务员上菜,然后所有人再开始吃. 实现原理: 使用 ReentrantLock.condition 实现的. 来一个线程,判断 count 自减后是否等于 0 ,不等于 0 ,则调用 wait 方法自我阻塞,等于 0 ,先执行传入的 runnable 线程,然后唤醒所有的线程. CyclicBarrier 和 ...
介绍: Semaphore 用于对某一物理或逻辑资源被同一时间访问数量的限制. 实现: Semaphore 是如何做到对某一物理或逻辑资源访问数量的限制了? 答案是 AQS. 比如我定义:Semaphore(10), 同一时刻只能有 10 个线程访问线程池,每来一个线程,state -1,当第11线程访问的结果是啥了?由于 state < 0 而被阻塞. 当一个线程访问完后,调用 release 方法,state + 1. 然后唤醒等待访问线程池的线程. 注意: 由于 release 方法中,没有对 state < 0 进行判断,每调用一次 release 方法 state + 1. ...
首先说明的是,这个和 ReadWriteLock 一样,同样是使用一个状态,包含两部分含义,一部分是线程池的运行状态,一个是线程池中的 Worker 数量. corePoolSize: 核心线程的数量. maximumPoolSize: 线程池中允许的最大线程数. keepAliveTime: 空闲线程等待的时间,超过这个时间,则销毁. largestPoolSize: 跟踪线程池中的最大线程数 allowCoreThreadTimeOut: 是否允许核心线程超时,若允许核心线程超时,那么 keepAliveTime 同样对核心线程有效. 当线程池执行 execute 方法时: 1.判断当前的线 ...
Java 并发中会大量使用到多线程,那么Java是如何使用多线程执行任务了? 线程池. 那线程池是如何调度任务的了? 按照我的理解是,Java 对 Runnable 或者 Callable 进行封装,Runnable 首先会被封装成 Callable, 然后对 Callable 做进一步的封装,封装成 FutureTask. 然后线程池调度 FutureTask, 但是实际上的执行还是通过 Runnable 或者 Callable 的 run 方法进行执行的.

Java Void 类型

    博客分类:
  • JAVA
今天看源码的时候发现了 Void 这个类型(不是 void) void 表示没有返回值,而 Void 表示返回 null.
public interface BlockingQueue<E> extends Queue<E> {     /**      * 插入指定元素到队列中,如果没有超出容量限制的话, 插入成功,返回 true. 如果没有空间的话,抛出 IllegalStateException.      * 当使用有容量限制的队列(queue)时,通常最好是使用 offer(Object) 方法.      *      */     boolean add(E e);     /**      * 插入指定元素到队列中,如果没有超出容量限制的话, 插入成功,返回 true, 如果没 ...
LinkedBlockingQueue 其实实现的是一个生产者消费者模式. 同一时刻,一个线程可以向队列中放东西,另一个时刻可以从队列中拿东西走. 如何实现多线程安全了? LinkedBlockingQueue 采用了 ReentrantLock 作为并发控制. 还有就是对 count 进行原子操作.
waiter 存放等待的线程,这是一个单链表,没有用 lock 或者 sync 但是实现了线程安全. static final class WaitNode {         // 记录当前线程.         volatile Thread thread;         // 指向下一个线程.         volatile WaitNode next;         WaitNode() { thread = Thread.currentThread(); }     } 这里为啥会使用 volatile 进行修饰了,而 Treober Stack 中则没有使用 volatile ...
boolean cancel(boolean mayInterruptIfRunning) 方法描述: /**      * Attempts to cancel execution of this task.  This attempt will      * fail if the task has already completed, has already been cancelled,      * or could not be cancelled for some other reason. If successful,      * and this task has not s ...

JAVA注解

    博客分类:
  • JAVA
5个基本的 Annotation 如下: @Override:指定方法重写 @Deprecation:标记已过时 @SuppressWarnings:抑制编译期警告,例如:@SuppressWarnings(value=“unchecked") @SafeVarargs @FunctionalInterface 自定义注解 Public @interface Test{ } 使用 @Test public class MyClass{ } 注解是一种标记,为一个类打上标记后,以后就可以通过反射来获取注解以及注解上的值,用于其他操作. 例如:Spring 中的 @Service 注解. ...
对于传统的服务:我们是知道它提供服务的地址(ip + port). 这时候,我们能够进行很方便的调用. 但是对于微服务就不同了,服务是动态分配的地址,所以无法像调用传统服务那样进行调用. 如何解决了? 习惯性的想法,我们可以找个代理(负载均衡器)呀,让它帮我们去查,查完后,调用服务.这种方式称为服务端发现. 还有一种想法就是,找代理多麻烦,我自己干(自己查),查完后,调用服务.这种方式称为客户端发现. 客户端发现方法中客户端和服务注册表之间存在很严重的耦合,导致每一个客户端都得写一套发现逻辑. 服务端发现就能避免这个问题.
Global site tag (gtag.js) - Google Analytics