啟動執行緒:增加程式中的處理流程。
優點:讓程式更有效率進行處理,例如進行要花費N鐘頭的迴圈處理時,可以別的執行緒進行其他處理。
注意:Thread一旦run結束或中斷,就再也無法呼叫start()重新啟動thread
1.執行緒實作方法有三種:
第一、extends Thread建立Thread的子類別obj1
Thread子類別建立物件後,呼叫start()(obj1.start())由Thread繼承而來)啟動執行緒,之後跑run()裡面的程式。如此一來可以分別建立物件,每個物件可以有自己執行緒。
第二、宣告類別obj並且implement Runnable,宣告執行緒類別,以obj為引數建立執行緒物件。
class CTest implements Runnable{
public run(){.....}}
public static main(String args[]){
CTest obj = new CTest();
CTest obj2 =new CTest();
Thread t1 = new Thread(obj);//產生執行緒物件
Thread t2 =new Thread(obj2);
t1.start();
t2.start();
}
第三、使用匿名內部類別
以上必須override run() method。
run()裡面的東西就是新處理流程的起點。
可以利用sleep(1000)暫時停止執行緒,這是暫停一秒。
class multi_thread implements Runnable{//實作thread第一步,implements Runnable
@Override
public void run() {//第二步改寫run(),
for(int i=1;i<=10;i++){
System.out.print("i="+i);//執行緒在這裡可能被插隊
System.out.println("name="+Thread.currentThread().getName());
try {
Thread.sleep(1500);//可以用Thread.sleep();讓執行緒進入blocked狀態(休息)
1500表示1.5秒,.sleep必須寫例外處理否則不給編譯過。
} catch (InterruptedException ex) {
} }
}}
public class runnable {
public static void main(String[] args) {
multi_thread obj = new multi_thread();
Thread thread1 = new Thread(obj,"Taiwan");//建立執行緒,thread1去跑obj的程式,並且將thread1的名稱命名為Taiwan
Thread thread2 = new Thread(obj,"Formosa");
thread1.setPriority(Thread.MIN_PRIORITY);//thread權限,括號裡面是int型態
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();//啟動thread
thread2.start();
try{
thread1.join();//.join()必須跟try-catch或throws InterruptedException配合
//thread1執行緒結束才會繼續執行try-catch之外的程式
thread2.join();//thread2執行緒執行完之後才會執行下面的程式
}catch(InterruptedException ex){}
System.out.println("finished");
}
}
同步synchronized
執行緒存取變數或物件時將資料lock住,禁止其他執行緒進行存取。
使用時機:多個執行緒在同一時間存取同一個變數或物件
避免資料不一致、插隊情形,避免互相等待造成死結。
常常與notify() wait()配合
notify():通知waiting狀態的執行緒,如果有多個thread則隨意喚醒其中一個
wait():執行去進入waiting狀態,必須等待其他執行緒呼叫notify()才能將它喚醒
以下是沒有synchronized的程式碼以及執行結果
某家公司有兩個司機,位公司開車賺錢,宣告company類別管理這兩名司機賺來的錢,兩名司機賺的錢交回公司。
class Company{
private int sum = 0;
public void add(int a){//若要正確結果,在這邊加上synchronized修飾
int tmp = sum;
System.out.println("目前合計金額"+tmp+"dollars");
System.out.println("賺到"+a);
tmp=tmp+a;
System.out.println("合計金額是"+tmp+"dollars");
sum=tmp;
}
}
class Driver implements Runnable{
private Company comp;
public Driver(Company c){
comp=c;
}
@Override
public void run(){
for(int i=0;i<3;i++)
{
System.out.println(Thread.currentThread().getName());//列印執行緒名字
comp.add(50);
}
}
}
public class synchron2 {
public static void main(String[] args) {
Company cmp = new Company();
Driver drv1= new Driver(cmp);
Thread thread1 = new Thread(drv1);
thread1.start();
Driver drv2=new Driver(cmp);
Thread thread2 = new Thread(drv2);
thread2.start();
}
}
執行結果:
Thread-0
目前合計金額 0dollars
賺到50
合計金額是50dollars
Thread-1
Thread-0
目前合計金額 50dollars //Thread1與Thread0幾乎同時讀取資料
目前合計金額 50dollars //這裡可以看到Thread1讀取到Thread0改過後的資料
賺到50
賺到50
合計金額是100dollars
Thread-0
目前合計金額100dollars
合計金額是100dollars
Thread-1
賺到50
目前合計金額100dollars
賺到50
合計金額是150dollars
合計金額是150dollars
Thread-1
目前合計金額150dollars
賺到50
合計金額是200dollars //正確金額應該是300元
沒有留言:
張貼留言