- 浏览: 78485 次
最新评论
-
kevinflynn:
...
ThreadLocal 源码分析 -
kevinflynn:
[url=aaaa][/url]
ThreadLocal 源码分析 -
kevinflynn:
学习到了 感谢楼主。
ThreadLocal 源码分析
文章列表
首先说明的是,这个和 ReadWriteLock 一样,同样是使用一个状态,包含两部分含义,一部分是线程池的运行状态,一个是线程池中的 Worker 数量.
corePoolSize: 核心线程的数量.
maximumPoolSize: 线程池中允许的最大线程数.
keepAliveTime: 空闲线程等待的时间,超过这个时间,则销毁.
largestPoolSize: 跟踪线程池中的最大线程数
allowCoreThreadTimeOut: 是否允许核心线程超时,若允许核心线程超时,那么 keepAliveTime 同样对核心线程有效.
当线程池执行 execute 方法时:
1 ...
Java 并发中会大量使用到多线程,那么Java是如何使用多线程执行任务了?
线程池.
那线程池是如何调度任务的了?
按照我的理解是,Java 对 Runnable 或者 Callable 进行封装,Runnable 首先会被封装成 Callable, 然后对 Callable 做进一步的封装,封装成 FutureTask. 然后线程池调度 FutureTask, 但是实际上的执行还是通过 Runnable 或者 Callable 的 run 方法进行执行的.
今天看源码的时候发现了 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 中则没有使用 volatil ...
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 ...
5个基本的 Annotation 如下:
@Override:指定方法重写
@Deprecation:标记已过时
@SuppressWarnings:抑制编译期警告,例如:@SuppressWarnings(value=“unchecked")
@SafeVarargs
@FunctionalInterface
自定义注解
Public @interface Test{
}
使用
@Test
public class MyClass{
}
注解是一种标记,为一个类打上标记后,以后就可以通过反射来获取注解以及注解上的值,用于其他操作.
例如:Spring 中的 @Serv ...
对于传统的服务:我们是知道它提供服务的地址(ip + port). 这时候,我们能够进行很方便的调用.
但是对于微服务就不同了,服务是动态分配的地址,所以无法像调用传统服务那样进行调用.
如何解决了?
习惯性的想法,我们可以找个代理(负载均衡器)呀,让它帮我们去查,查完后,调用服务.这种方式称为服务端发现.
还有一种想法就是,找代理多麻烦,我自己干(自己查),查完后,调用服务.这种方式称为客户端发现.
客户端发现方法中客户端和服务注册表之间存在很严重的耦合,导致每一个客户端都得写一套发现逻辑.
服务端发现就能避免这个问题.
首先说下为啥会有限流:
比如说:双11,全民购物狂欢节,虽然我们买东西可开心了,但是会有一个问题. 比如说淘宝服务本来只能支持 10 个人同时访问,但是在有 10000 个人同时访问了,这就会导致系统资源耗尽,最终服务崩掉.
限流的目的是为了控制访问的流量. 比如说它支持10人访问,那么我就控制每次只有10个人访问.
限流的策略:
1.令牌桶:
首先这个桶是有容量的,比如说10.然后每秒钟向桶中放 x 个令牌,当放入的令牌总数 > 桶的容量时,则溢出.(拒绝服务). 每次请求来了,需要先去桶中获取一个令牌才能执行(消费令牌).这样就能控制访问的数量了.
可以理解为生产者-消费者模 ...
在互联网项目中,会大量的用到缓存,例如:
192.168.0.10/192.168.0.11/192.168.0.12 三台机器上都有缓存.
现在用户A 要查询 key 对应的 value 放在那台机器上,那应该怎么处理了?
一般的思路是通过模运算来解决,例如:用 x % N 的结果去对应的机器上去查找.
比如:1 = x % N, 那么就去 192.168.0.10 这台机器上查找.
但是这有一个问题,当一个机器宕机的时候,或者随着访问量的增大,需要新增加机器,那么这时候,通过模运算将会存在大量的不命中. 因为不管是宕机或者新增加机器,都会涉及到 N 的变化,就会导致和以前存储时获得的 ...
/*
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package com.hanlin.fadp;
import java.lang.ref.*;
/**
* This class extends <tt&g ...
说明:
每个线程内部持有一个 ThreadLocalMap 的东西,而我发现 ThreadLocal 内中 nextHashCode 为静态变量,这就意味着该变量为所有 ThreadLocal 锁共有.
现在考虑一种极端情况,有两个 ThreadLocal 实例:ThreadLocalA 和 ThreadLocalB. 两个线程:ThreadA 和 ThreadB.
ThreadLocalA 存有线程A和线程B的数据. 反应到底层的数据结构是:
ThreadA.ThreadLocalMap<ThreadLocalA, Value>
ThreadB.ThreadLocalMap ...
1.首先说明 ReentrantReadWriteLock 和 IO操作没有关系,只是说将读操作和写操作分开,提高性能
2.实现原理:
用 state 的高 16 位表示读锁的数量,用 state 的低 16位表示写锁的数量
可以申请到写锁的条件:
1.没有线程持有锁(读锁和写锁,锁是不能升级的,比如说当前线程持有读锁,但是后面该线程申请不到写锁)
2.当前线程持有写锁(这种情况时说,本线程已经持有锁了,换句话说,WriteLock 是可重入锁)
可以申请到读锁的条件:
1.没有线程持有锁
2.当前线程持有写锁
CountDownLatch 源码分析
- 博客分类:
- JAVA 并发
思路分析:
CountDownLatch 的思路是:首先申请锁的时候,假设以 6 申请锁. 此时线程阻塞. 参考独占锁中的重入锁.
此时:假设一个独占锁多次申请锁的话,那么假设此时 state = 6.
这时候就跟共享锁初始的时候申请锁差不多了.
现在每调用一次 countDown 方法的时候,state -1
当 state = 0 的时候,是不是说明没有再占用锁了?那么此时线程就可以执行了.
CountDownLatch 的实现思路从始至终只有一个线程在队列中,也就是主线程.
它的 countDown 方法只是将 state 减一. 当 count=0时,调用 doRe ...