線程的創建和啟動 java語言已經內置了多線程支持
所有實現Runnable接口的類都可被啟動一個新線程
新線程會執行該實例的run()方法
當run()方法執行完畢後
線程就結束了
一旦一個線程執行完畢
這個實例就不能再重新啟動
只能重新生成一個新實例
再啟動一個新線程
Thread類是實現了Runnable接口的一個實例
它代表一個線程的實例
並且
啟動線程的唯一方法就是通過Thread類的start()實例方法
Thread t = new Thread();
t
start();
start()方法是一個native方法
它將啟動一個新線程
並執行run()方法
Thread類默認的run()方法什麼也不做就退出了
注意
直接調用run()方法並不會啟動一個新線程
它和調用一個普通的java方法沒有什麼區別
因此
有兩個方法可以實現自己的線程
方法
自己的類extend Thread
並復寫run()方法
就可以啟動新線程並執行自己定義的run()方法
例如
public class MyThread extends Thread {
public run() {
System
out
println(
MyThread
run()
);
}
}
在合適的地方啟動線程
new MyThread()
start();
方法
如果自己的類已經extends另一個類
就無法直接extends Thread
此時
必須實現一個Runnable接口
public class MyThread extends OtherClass implements Runnable {
public run() {
System
out
println(
MyThread
run()
);
}
}
為了啟動MyThread
需要首先實例化一個Thread
並傳入自己的MyThread實例
MyThread myt = new MyThread();
Thread t = new Thread(myt);
t
start();
事實上
當傳入一個Runnable target參數給Thread後
Thread的run()方法就會調用target
run()
參考JDK源代碼
public void run() {
if (target != null) {
target
run();
}
}
線程還有一些Name
ThreadGroup
isDaemon等設置
由於和線程設計模式關聯很少
這裡就不多說了
線程同步 由於同一進程內的多個線程共享內存空間
在Java中
就是共享實例
當多個線程試圖同時修改某個實例的內容時
就會造成沖突
因此
線程必須實現共享互斥
使多線程同步
最簡單的同步是將一個方法標記為synchronized
對同一個實例來說
任一時刻只能有一個synchronized方法在執行
當一個方法正在執行某個synchronized方法時
其他線程如果想要執行這個實例的任意一個synchronized方法
都必須等待當前執行synchronized方法的線程退出此方法後
才能依次執行
但是
非synchronized方法不受影響
不管當前有沒有執行synchronized方法
非synchronized方法都可以被多個線程同時執行
此外
必須注意
只有同一實例的synchronized方法同一時間只能被一個線程執行
不同實例的synchronized方法是可以並發的
例如
class A定義了synchronized方法sync()
則不同實例a
sync()和a
sync()可以同時由兩個線程來執行
Java鎖機制 多線程同步的實現最終依賴鎖機制
我們可以想象某一共享資源是一間屋子
每個人都是一個線程
當A希望進入房間時
他必須獲得門鎖
一旦A獲得門鎖
他進去後就立刻將門鎖上
於是B
C
D
就不得不在門外等待
直到A釋放鎖出來後
B
C
D
中的某一人搶到了該鎖(具體搶法依賴於JVM的實現
可以先到先得
也可以隨機挑選)
然後進屋又將門鎖上
這樣
任一時刻最多有一人在屋內(使用共享資源)
Java語言規范內置了對多線程的支持
對於Java程序來說
每一個對象實例都有一把
鎖
一旦某個線程獲得了該鎖
別的線程如果希望獲得該鎖
只能等待這個線程釋放鎖之後
獲得鎖的方法只有一個
就是synchronized關鍵字
例如
public class SharedResource {
private int count =
;
public int getCount() { return count; }
public synchronized void setCount(int count) { unt = count; }
}
同步方法public synchronized void setCount(int count) { unt = count; } 事實上相當於
public void setCount(int count) {
synchronized(this) { // 在此獲得this鎖
unt = count;
} // 在此釋放this鎖
}
紅色部分表示需要同步的代碼段
該區域為
危險區域
如果兩個以上的線程同時執行
會引發沖突
因此
要更改SharedResource的內部狀態
必須先獲得SharedResource實例的鎖
退出synchronized塊時
線程擁有的鎖自動釋放
於是
別的線程又可以獲取該鎖了
為了提高性能
不一定要鎖定this
例如
SharedResource有兩個獨立變化的變量
public class SharedResouce {
private int a =
;
private int b =
;
public synchronized void setA(int a) { this
a = a; }
public synchronized void setB(int b) { this
b = b; }
}
若同步整個方法
則setA()的時候無法setB()
setB()時無法setA()
為了提高性能
可以使用不同對象的鎖
public class SharedResouce {
private int a =
;
private int b =
;
private Object sync_a = new Object();
private Object sync_b = new Object();
public void setA(int a) {
synchronized(sync_a) {
this
a = a;
}
}
public synchronized void setB(int b) {
synchronized(sync_b) {
this
b = b;
}
}
}
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27460.html