Java多线程系列
1、参考资料(多线程系列)
1、:Java多线程系列目录
1.1、基础篇
02. Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式
03. Java多线程系列--“基础篇”03之 Thread中start()和run()的区别
04. Java多线程系列--“基础篇”04之 synchronized关键字
05. Java多线程系列--“基础篇”05之 线程等待与唤醒
08. Java多线程系列--“基础篇”08之 join()
09. Java多线程系列--“基础篇”09之 interrupt()和线程终止方式
10. Java多线程系列--“基础篇”10之 线程优先级和守护线程
11. Java多线程系列--“基础篇”11之 生产消费者问题
1.2、JUC原子类
13. Java多线程系列--“JUC原子类”02之 AtomicLong原子类
14. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类
15. Java多线程系列--“JUC原子类”04之 AtomicReference原子类
16. Java多线程系列--“JUC原子类”05之 AtomicLongFieldUpdater原子类
1.3、JUC锁
18. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
19. Java多线程系列--“JUC锁”03之 公平锁(一)
20. Java多线程系列--“JUC锁”04之 公平锁(二)
22. Java多线程系列--“JUC锁”06之 Condition条件
23. Java多线程系列--“JUC锁”07之 LockSupport
24. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
25. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
26. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
27. Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例
1.4、JUC集合
29. Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
30. Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
31. Java多线程系列--“JUC集合”04之 ConcurrentHashMap
32. Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap
33. Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
34. Java多线程系列--“JUC集合”07之 ArrayBlockingQueue
35. Java多线程系列--“JUC集合”08之 LinkedBlockingQueue
36. Java多线程系列--“JUC集合”09之 LinkedBlockingDeque
37. Java多线程系列--“JUC集合”10之 ConcurrentLinkedQueue
1.5、JUC线程池
38. Java多线程系列--“JUC线程池”01之 线程池架构
39. Java多线程系列--“JUC线程池”02之 线程池原理(一)
40. Java多线程系列--“JUC线程池”03之 线程池原理(二)
41. Java多线程系列--“JUC线程池”04之 线程池原理(三)
42. Java多线程系列--“JUC线程池”05之 线程池原理(四)
43. Java多线程系列--“JUC线程池”06之 Callable和Future
2、简要总结
多线程是Java中不可避免的一个重要主体。从本章开始,我们将展开对多线程的学习。接下来的内容,是对“JDK中新增JUC包”之前的Java多线程内容的讲解,涉及到的内容包括,Object类中的wait(), notify()等接口;Thread类中的接口;synchronized关键字。
注:JUC包是指,Java.util.concurrent包,它是由Java大师Doug Lea完成并在JDK1.5版本添加到Java中的。
2.1、线程状态
说明:
线程共包括以下5种状态。
1. 新建状态(New) : 线程对象被创建但还没有调用start方法时,处于新建状态。例如,Thread thread = new Thread()。
2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
3. 运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
4. 阻塞状态(Blocked) : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
(02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
(03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead) : 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
线程的5种状态涉及到的内容包括Object类, Thread和synchronized关键字。这些内容我们会在后面的章节中逐个进行学习。
Object类,定义了wait(), notify(), notifyAll()等休眠/唤醒函数。
Thread类,定义了一些列的线程操作函数。例如,sleep()休眠函数, interrupt()中断函数, getName()获取线程名称等。
Java线程状态:
注:其实Java在Thread类中定义了线程的状态(enum State),共有六种:NEW、RUNNABLE、TERMINATED、BLOCKED、WAITING、TIMED_WAITING。
- RUNNABLE包括上述的Runnable和Running。
- WAITING表示无线等待,需要被唤醒,如执行wait()、join()方法
- TIMED_WAITING表示有限等待,在一定时间后自动唤醒,如执行wait(long timems)、join(long timems)、sleep(long timems)方法
- BLOCKED表示阻塞,线程等待进入同步区时进入此状态
2.2、线程状态转换方法
详见:Java线程状态及 join、sleep、wait、notify、yield等的区别
2.3、同步互斥
同步:在多个线程并发访问共享数据时,保证数据在同一时刻只被一个(或一些,使用信号量的时候)线程使用。可以分为阻塞同步(如互斥)和非阻塞同步(需要硬件指令集的发展以保障“操作和冲突检测”的原子性,CAS操作等)。
互斥:实现同步的一种手段,属于阻塞同步。临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)是主要的互斥实现方式
互斥是因,同步是果;互斥是方法,同步是目的。
2.4、线程协作
待...
2.5、线程竞争
多线程共享内存(竞争访问同一资源)带来的问题:(参考资料:http://mp.weixin.qq.com/s/DC6JlRo7LEx4rRsz9U_Xpw)
1、竞态条件(race condition):当多个线程访问和操作同一个对象时,最终执行结果与执行时序有关,可能正确也可能不正确
解决:
- 使用synchronized关键字(相关:synchronized关键字)
- 使用显式锁
- 使用原子变量(计数、序号等场景)或原子更新(被更新的变量需被volatile修饰)
// 2、原子变量
// 对于count++这种操作来说,使用synchronzied成本太高了,需要先获取锁,最后还要释放锁,获取不到锁的情况下还要等待,还会有线程的上下文切换,这些都需要成本。
//
// 对于这种情况,完全可以使用原子变量代替,Java并发包中的基本原子变量类型有:
// AtomicBoolean:原子Boolean类型
// AtomicInteger:原子Integer类型
// AtomicLong:原子Long类型
// AtomicReference:原子引用类型
class AtomicIntegerDemo {
private static AtomicInteger counter = new AtomicInteger(0); static class Visitor extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
counter.incrementAndGet();
Thread.yield();
}
}
} public static void main(String[] args) throws InterruptedException {
int num = 100;
Thread[] threads = new Thread[num];
for (int i = 0; i < num; i++) {
threads[i] = new Visitor();
threads[i].start();
}
for (int i = 0; i < num; i++) {
threads[i].join();
}
System.out.println(counter.get());
}
} // 原子更新
class FieldUpdaterDemo {
static class DemoObject {// 类DemoObject中有两个成员num和ref,声明为volatile,但不是原子变量,不过DemoObject对外提供了原子更新方法compareAndSet,它是使用字段对应的FieldUpdater实现的,FieldUpdater是一个静态成员,通过newUpdater工厂方法得到,newUpdater需要的参数有类型、字段名、对于引用类型,还需要引用的具体类型。
private volatile int num;
private volatile Object ref; private static final AtomicIntegerFieldUpdater<DemoObject> numUpdater = AtomicIntegerFieldUpdater
.newUpdater(DemoObject.class, "num");
private static final AtomicReferenceFieldUpdater<DemoObject, Object> refUpdater = AtomicReferenceFieldUpdater
.newUpdater(DemoObject.class, Object.class, "ref"); public boolean compareAndSetNum(int expect, int update) {
return numUpdater.compareAndSet(this, expect, update);
} public int getNum() {
return num;
} public Object compareAndSetRef(Object expect, Object update) {
return refUpdater.compareAndSet(this, expect, update);
} public Object getRef() {
return ref;
}
} public static void main(String[] args) {
DemoObject obj = new DemoObject();
obj.compareAndSetNum(0, 100);
obj.compareAndSetRef(null, new String("hello"));
System.out.println(obj.getNum());
System.out.println(obj.getRef());
}
}
2、内存可见性:多个线程可以共享访问和操作相同的变量,但一个线程对一个共享变量的修改,另一个线程不一定马上就能看到,甚至永远也看不到
解决:
- 使用volatile关键字(相关:volatile关键字)
- 使用synchronized关键字同步
- 使用显式锁同步
2.6、 对象的线程安全
1、线程安全:(Brian Goetz《Java Concurrency In Practice》)当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步或在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那此对象是线程安全的。
此定义要求线程安全的代码都必须具备一个特征:代码本身封装了所有必要的正确性保障手段(如互斥同步等),令调用者无须关心多线程的问题,更无须采取任何措施保证多线程的正确调用。此并不易做到,在大多数场景中,会将此定义弱化些,若把“调用这个对象的行为”限定为“单次调用”,此定义的其他描述也能成立,则称之是线程安全的了。
2、保证线程安全的思路
- 锁,使用synchronized或ReentrantLock(悲观策略),参看理解synchronized
- 原子操作,循环CAS(乐观策略),参看原子变量和CAS
- 写时拷贝,如CopyOnWriteArrayList,适用于元素个数不多,绝大部分访问都是读,且有大量并发线程要求读,只有个别线程进行写,且只是偶尔写的场合。(参看写时拷贝的List和Set)
Java多线程系列的更多相关文章
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
- Java多线程系列--“JUC锁”01之 框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
- Java多线程系列目录(共43篇)
最近,在研究Java多线程的内容目录,将其内容逐步整理并发布. (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线 ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java多线程系列--“JUC锁”05之 非公平锁
概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...
随机推荐
- mybatis Generator配置文件详解
这里按照配置的顺序对配置逐个讲解,更细的内容可以配合中文文档参照. 1. 配置文件头 <?xml version="1.0" encoding="UTF-8&quo ...
- 高手详解SQL性能优化十条经验
1.查询的模糊匹配 尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用. 解决办法: 其实只需要对该脚本略做改进,查询速度便会 ...
- 大屏iPhone的适配 +iOS 图片尺寸要求
摘自:http://blog.ibireme.com/2014/09/16/adapted_to_iphone6/ 苹果公司官网设计介绍到:Retina显示屏的超高像素密度已超过人眼能分辨的范围.Re ...
- ps还能用脚本切片?
最近在慕课网上看有关于ps切图的视频,发现ps 切片的水还挺深的.这相当于我的一篇学习笔记吧.对于ps的基本切图我觉得对于前端人员来说就是a piece of cake.但是对于ps的精准切图,我不知 ...
- BZOJ 3709: [PA2014]Bohater
3709: [PA2014]Bohater Time Limit: 5 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1050 Solved: ...
- BZOJ 1113: [Poi2008]海报PLA
1113: [Poi2008]海报PLA Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1025 Solved: 679[Submit][Statu ...
- 【BZOJ-1441】Min 裴蜀定理 + 最大公约数
1441: Min Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 471 Solved: 314[Submit][Status][Discuss] De ...
- hdu 3089 约瑟夫环
原来并不知道约瑟夫环还可以递推直接解orz 约瑟夫问题的递推公式: 设f[n]表示一共n个人,数到k出局,这样最后的winner (n个人从0开始标号,即0--n-1) f[n]=(f[n-1]+k) ...
- Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platform)
catalog . 引言 . Windows 2000网络结构和OSI模型 . NDIS驱动 . NDIS微端口驱动编程实例 . NDIS中间层驱动编程实例 . NDIS协议层驱动编程实例 . TDI ...
- Eclipse 代码自动补全配置方法
Eclipse默认只有在出现 “.”时才进行代码提示,更改方法为: 即把“.”改为“.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”,表示输 ...