java多线程开发手册

### Java多线程

进程和线程的概念

进程和线程的区别

Java语言内置多线程支持

多线程编程的特点:

* 多线程需要读写共享数据

* 多线程经常需要同步

* 多线程编程的复杂度高,调试更困难

### 创建新线程

1. 从Thread派生

2. 实现Runnable接口

必须调用`start()`方法才能启动新线程

`Thread.sleep()`可以把当前线程暂停一段时间

### 线程的状态

一个线程对象只能调用一次start()

Java线程对象Thread的状态包括:

New / Runnable / Blocked / Waiting / Timed Waiting / Terminated

通过对另一个线程对象调用join()方法可以等待其执行结束

可以指定等待时间,超过等待时间线程仍然没有结束就不再等待

对已经运行结束的线程调用join()方法会立刻返回

### 中断线程

调用interrupt()方法可以中断一个线程

通过检测isInterrupted()标志获取当前线程是否已中断

如果线程处于等待状态,该线程会捕获InterruptedException

isInterrupted()为true或者捕获了InterruptedException都应该立刻结束

通过标志位判断需要正确使用volatile关键字

volatile关键字解决了共享变量在线程间的可见性问题

### 守护线程

守护线程是为其他线程服务的线程

所有非守护线程都执行完毕后,虚拟机退出

守护线程不能持有资源(如打开文件等)

创建守护线程:setDaemon(true)

### 线程同步

多线程同时修改变量,会造成逻辑错误

需要通过synchronized同步

同步的本质就是给指定对象加锁

注意加锁对象必须是同一个实例

对JVM定义的单个原子操作不需要同步

### synchronized方法

用synchronized修饰方法可以把整个方法变为同步代码块

synchronized方法加锁对象是this

通过合理的设计和数据封装可以让一个类变为“线程安全”

一个类没有特殊说明,默认不是thread-safe

多线程能否访问某个非线程安全的实例,需要具体问题具体分析

### 死锁

死锁产生的条件:

多线程各自持有不同的锁,并互相试图获取对方已持有的锁,双方无限等待下去:导致死锁

如何避免死锁:

多线程获取锁的顺序要一致

### wait / notify

wait / notify用于多线程协调运行:

在synchronized内部可以调用wait()使线程进入等待状态

必须在已获得的锁对象上调用wait()方法

在synchronized内部可以调用notify / notifyAll()唤醒其他等待线程

必须在已获得的锁对象上调用notify / notifyAll()方法

### ReentrantLock

ReentrantLock可以替代synchronized

ReentrantLock获取锁更安全

必须使用`try … finally`保证正确获取和释放锁

`tryLock()`可指定超时

### ReadWriteLock

使用ReadWriteLock可以提高读取效率:

* ReadWriteLock只允许一个线程写入

* ReadWriteLock允许多个线程同时读取

* ReadWriteLock适合读多写少的场景

### Condition

Condition可以替代wait / notify

Condition对象必须从ReentrantLock对象获取

ReentrantLock+Condition可以替代synchronized + wait / notify

### concurrent集合

使用java.util.concurrent提供的Blocking集合可以简化多线程编程:

* CopyOnWriteArrayList

* ConcurrentHashMap

* CopyOnWriteArraySet

* ArrayBlockingQueue

* LinkedBlockingQueue

* LinkedBlockingDeque

多线程同时访问Blocking集合是安全的

尽量使用JDK提供的concurrent集合,避免自己编写同步代码

### Atomic

使用java.util.atomic提供的原子操作可以简化多线程编程:

AtomicInteger/AtomicLong/AtomicIntegerArray等

原子操作实现了无锁的线程安全

适用于计数器,累加器等

### ExecutorService

JDK提供了ExecutorService实现了线程池功能

线程池内部维护一组线程,可以高效执行大量小任务

Executors提供了静态方法创建不同类型的ExecutorService

常用ExecutorService:

* FixedThreadPool:线程数固定

* CachedThreadPool:线程数根据任务动态调整

* SingleThreadExecutor:仅单线程执行

必须调用shutdown()关闭ExecutorService

ScheduledThreadPool可以定期调度多个任务(可取代Timer)

### Future

Future表示一个未来可能会返回的结果

提交Callable任务,可以获得一个Future对象

可以用Future在将来某个时刻获取结果

### CompletableFuture

CompletableFuture的优点:

* 异步任务结束时,会自动回调某个对象的方法

* 异步任务出错时,会自动回调某个对象的方法

* 主线程设置好回调后,不再关心异步任务的执行

CompletableFuture对象可以指定异步处理流程:

* thenAccept()处理正常结果

* exceptional()处理异常结果

* thenApplyAsync() 用于串行化另一个CompletableFuture

* anyOf / allOf 用于并行化两个CompletableFuture

### Fork/Join

Fork/Join是一种基于“分治”的算法:分解任务+合并结果

ForkJoinPool线程池可以把一个大任务分拆成小任务并行执行

任务类必须继承自RecursiveTask/RecursiveAction

使用Fork/Join模式可以进行并行计算提高效率

调用Thread.currentThread()获取当前线程。

JDK提供了ThreadLocal,在一个线程中传递同一个对象。

ThreadLocal表示线程的“局部变量”,它确保每个线程的ThreadLocal变量都是各自独立的。

ThreadLocal适合在一个线程的处理流程中保持上下文(避免了同一参数在所有方法中传递)

使用ThreadLocal要用try … finally结构。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容