- ReenterLock
- 可重入锁代表着一个线程可以多次获得同一把锁
- 中断响应,IntLock
- 锁申请等待限时,TimeLock
- 不带参数的TryLock
- 公平锁需要维护一个有序队列,成本高,默认是非公平锁,FairLock
重入锁的实现主要包含三个要素:
- 原子状态,CAS
- 等待队列
- 阻塞原语park()和unpark()
- wait和notify是和synchronize合作使用的,condition是和重入锁相关联的,ReenterLockCondition
- 实践了一下果然速度差距相当大
- ReadWriteLockDemo
- 这个理解起来难度大一些
- CyclicBarrierDemo
- LockSupport的park和unpark函数,和suspend和resume函数比,不存在先后顺序,也就不会由于先resume后suspend导致程序死掉
- 和信号量的区别是它只有一个许可,而信号量可以有多个
- LockSupportDemo
- LockSupportIntDemo
-
类图要好好看看,建议阅读jdk源代码了解下关系,整理如下:
- ExecutorService继承了Executor
- AbstractExecutorService实现了ExecutorService接口
- Executors生成了ThreadPoolExecutor
-
Executors中包含的一部分线程池类型:
- newFixedThreadPool,ThreadPoolDemo
- newSingleThreadExecutor
- newCachedThreadPool
- newSingleThreadScheduledExecutor
- newScheduledThreadPool
- FixedRate是从上一个任务开始后计时,ScheduledExecutorServiceDemo
- FixedDelay是从上一个任务结束后计时
- 均使用ThreadPoolExecutor实现,最全的构造函数如下
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}workQueue和handler需要特别理解一下,核心执行代码如下:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}- 四种系统定义的拒绝策略代码
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}- 比较了一下ExecuteService中submit和execute函数的区别,通过观察发现,sumit最终也会执行execute函数,具体分析可见这篇文章
- 顺着execute函数的位置,列一下这几个类的关系,代码如下:
//最上层Executor接口
public interface Executor {
void execute(Runnable command);
}
//继承了Executor接口的ExecutorService接口
public interface ExecutorService extends Executor {
//中间各种函数,但不包含execute函数
}
//实现了ExecutorService接口的AbstractExecutorService抽象类
public abstract class AbstractExecutorService implements ExecutorService {
//省略其他函数...
//submit函数内调用了execute,但该抽象类没有execute函数的具体实现
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);//调用了Executor的execute方法
return ftask;
}
}
//实现了AbstractExecutorService抽象类的ThreadPoolExecutor类
public class ThreadPoolExecutor extends AbstractExecutorService {
//省略其他函数...
//execute函数的具体实现
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
}请见书中公式
- 程序的本质意思就是写一个类重写execute和submit方法,加一个包装,让该包装可以抛出异常信息
- TraceThreadPoolExecutor
- 本质就是一种递归的调用,然后不断缩小规模直到可以计算,最后将结果加起来
- CountTask
- 本节代码都是
java.util.concurrent;包中的源代码,故而不修改每个文件的包引入行,保持代码原有的样子,方便读者观看
注:此处使用JDK1.7的源代码
- ConcurrentHashMap,线程安全的HahsMap
- CopyOnWriteArrayList,线程安全的ArrayList一族
- ConcurrentLinkedQueue,线程安全的LinkedList
- BlockingQueue,阻塞队列
- ConcurrentSkipListMap,跳表,用于快速查找
- 将HashMap变为线程安全的,可用以下方法,但并发级别不高
public static Map m=Collections.synchronizedMap(new HashMap());- 更加专业的并发HashMao是ConcurrentHashMap
- 将List变为线程安全的,可用以下方法
public static List<String> l=Collections.synchronizedList(new LinkedList<String>());- 更加专业的并发HashMap是ConcurrentHashMap
- 这里很难,还要再读一遍再做笔记!!!!!
- 读读不冲突,读写不冲突,只有写写冲突
- 在写的时候先做一次数据复制,将修改的内容写入副本中,再讲副本替换原来的数据
- CopyOnWriteArrayList