最近讀完了《java多線程編程核心技術(shù)》(高洪巖)间雀、《Android高性能編程》(葉坤 譯)悔详、《Java RESTful Web Service實(shí)戰(zhàn) (第2版)》(韓陸),覺(jué)得有必要記錄下惹挟。先從《java多線程編程核心技術(shù)》開(kāi)始茄螃。
廢話不多說(shuō),上思維導(dǎo)圖
1连锯、線程常用方法
(1)繼承Thread归苍、實(shí)現(xiàn)Runnable接口
(2)共享數(shù)據(jù)可能會(huì)出現(xiàn)線程不安全問(wèn)題
(3)isAlive 判斷線程是否處于活動(dòng)狀態(tài)
(4)sleep 線程進(jìn)入休眠
(5)停止線程
this.interrupted() 測(cè)試當(dāng)前線程是否已經(jīng)是中斷狀態(tài),執(zhí)行后對(duì)狀態(tài)有清除為false的功能
this.isInterrupted() 測(cè)試線程Thread對(duì)象是否已經(jīng)是中斷狀態(tài)运怖,但不清除狀態(tài)標(biāo)志
可以通過(guò)Throw new Exception中斷線程運(yùn)行
stop方法已經(jīng)不建議繼續(xù)使用
(6)暫停拼弃、恢復(fù)線程
suspend、resume 該組方法有獨(dú)占摇展、不同步的缺點(diǎn)
yield放棄當(dāng)前占用的cpu資源吻氧,但暫停時(shí)間不確定
(7)線程可以設(shè)置優(yōu)先級(jí) 1~10的級(jí)別,默認(rèn)5咏连,最小1盯孙,最大10,小于1或者大于10都會(huì)拋異常
2捻勉、對(duì)象及變量的并發(fā)訪問(wèn)
synchronized保護(hù)的是對(duì)象
同步實(shí)例方法(同步當(dāng)前對(duì)象)
int count = 0;
public synchronized void add() {
count++;
}
同步靜態(tài)方法(同步當(dāng)前類(lèi))
static int count = 0;
public static synchronized void add() {
count++;
}
同步代碼塊
(實(shí)例镀梭,同步當(dāng)前對(duì)象)
int count = 0;
public void add() {
synchronized(this) {
count++;
}
}
(靜態(tài)刀森,同步當(dāng)前類(lèi))
static int count = 0;
public static void add() {
synchronized(Counter.class) {
count++;
}
}
(使用單獨(dú)對(duì)象作為鎖)
int count = 0;
Object object = new Object();
public void add() {
synchronized(object) {
count++;
}
}
可重入性/內(nèi)存可見(jiàn)性/死鎖
volatile 變量存在于線程外部的內(nèi)存空間踱启,能保證變量是最新值,只能保證可見(jiàn)性研底,不能保證原子性埠偿,就是說(shuō)不能保證變量的同步安全。
3榜晦、線程間通信
(1)等待/通知機(jī)制
wait方法是Object類(lèi)的方法冠蒋,必須要配合監(jiān)視器(synchronized)一起使用,監(jiān)視器監(jiān)視的是對(duì)象乾胶。
public static void main(String[] args) {
try {
Object lock = new Object();
ThreadA threadA = new ThreadA(lock);
threadA.start();
Thread.sleep(2000);
ThreadB threadB = new ThreadB(lock);
threadB.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public static class ThreadA extends Thread {
private Object lock;
public ThreadA(Object lock) {
this.lock = lock;
}
@Override
public void run() {
try {
synchronized (lock) {
System.out.println("開(kāi)始 wait time:" + System.currentTimeMillis());
lock.wait();
System.out.println("結(jié)束 wait time:" + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static class ThreadB extends Thread {
private Object lock;
public ThreadB(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("開(kāi)始 notify time:" + System.currentTimeMillis());
lock.notify();
System.out.println("結(jié)束 notify time:" + System.currentTimeMillis());
}
}
}
notifyAll 可以喚醒所有持有該對(duì)象鎖的線程抖剿,讓其繼續(xù)執(zhí)行剩余的操作朽寞。
(2)通過(guò)管道進(jìn)行線程間通信(字節(jié)流/字符流)
(3)join方法的使用
public static void main(String[] args) {
try {
ThreadA thread = new ThreadA();
thread.start();
thread.join();
System.out.println("我在Thread執(zhí)行完成后,執(zhí)行了這個(gè)log");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static class ThreadA extends Thread {
@Override
public void run() {
try {
int secondValue = (int)(Math.random() * 10000);
System.out.println(secondValue);
Thread.sleep(secondValue);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
join 會(huì)釋放鎖斩郎,sleep 內(nèi)部用的是sychronized脑融,所以sleep不會(huì)釋放鎖。
(3)ThreadLocal 相關(guān)內(nèi)容
ThreadLocal解決的是每個(gè)線程綁定自己的值缩宜,就想一個(gè)線程安全的盒子保存這線程的數(shù)據(jù)肘迎。
InheritableThreadLocal 可以在子線程中取得副線程傳承下來(lái)的值。InheritableThreadLocal是ThreadLocal的子類(lèi)锻煌。
4妓布、Lock的使用
ReentrantLock類(lèi)從jdk1.5開(kāi)始進(jìn)行支持。除了可以實(shí)現(xiàn)synchronized的的同步鎖功能外宋梧,還可以實(shí)現(xiàn)嗅探鎖定匣沼、多路分支通知等功能。
(1)基本使用
private Lock lock = new ReentrantLock();
try {
lock.lock();
.............
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
(2)Condition實(shí)現(xiàn)等待/通知
Object類(lèi)中的wait()相當(dāng)于Condition中的await();
Object類(lèi)中的wait(long timeout)相當(dāng)于Condition中的await(long time, TimeUnit unit);
Object類(lèi)中的notify()相當(dāng)于Condition中的signal();
Object類(lèi)中的notifyAll()相當(dāng)于Condition中的signalAll();
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
MyService myService = new MyService();
ThreadA threadA = new ThreadA(myService);
threadA.start();
Thread.sleep(3000);
myService.signal();
}
private static class MyService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void await() {
try {
lock.lock();
System.out.println("await 時(shí)間為" + System.currentTimeMillis());
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal() {
try {
lock.lock();
System.out.println("signal 時(shí)間為" + System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
}
private static class ThreadA extends Thread {
private MyService myService;
public ThreadA(MyService myService) {
this.myService = myService;
}
@Override
public void run() {
// TODO Auto-generated method stub
myService.await();
}
}
(3)公平鎖 非公平鎖
公平鎖先來(lái)先獲得鎖捂龄;非公平鎖先來(lái)不一定會(huì)獲得鎖肛著,有可能會(huì)導(dǎo)致一些線程一直沒(méi)獲得鎖。
Lock lock = new ReentrantLock(boolean isFair);
(4)各種方法
getHoldCount()跺讯、 getQueueLength()枢贿、getWaitQueueLength()
hasQueueThread()、hasQueueThreads()刀脏、hasWaiters()
isFair()局荚、isHeldByCurrentThread()、isLocked()
lockInterruptibly()愈污、tryLock()耀态、tryLock(long timeout, TimeUnit unit)
awaitUninterruptibly()、awaitUntil()
(5)ReentrantReadWriteLock讀寫(xiě)鎖
有兩個(gè)鎖暂雹,一個(gè)讀鎖首装,一個(gè)寫(xiě)鎖
多個(gè)讀鎖之間不互斥,讀鎖與寫(xiě)鎖互斥杭跪,寫(xiě)鎖與寫(xiě)鎖互斥
O了仙逻。