1,兩種方法來建立線程:
1)繼承Thread類實現run方法:
public class Hello1 extends Thread{String name;public Hello1(String n){name = n;}public void run(){for (int i=1; i<=10; i++){System.out.println(name+" Hello "+i);}}}
2)實現Runnable介面,實現run方法:
public class Hello2 implements Runnable{String name;public Hello2(String n){name = n;}public void run(){for (int i=1; i<=10; i++)System.out.println(name+" Hello "+i);}}
推薦第二種方法;
2,產生Thread對象和啟動線程
public class ThreadsExample1{public static void main(String argv[]){Hello1 h1 = new Hello1("Thread1");Hello2 h2 = new Hello2("Thread2");Thread t1 = new Thread(h1);Thread t2 = new Thread(h2);t1.start();t2.start();}}
3,停止線程運行
下面的run方法可以讓線程一直運行:
public class Hello3 implements Runnable{String name;public Hello3(String n){name = n;}public void run(){int i=0;while(true)//這樣來寫run方法{i++;System.out.println(name+" Hello "+i);}}}
加一個迴圈條件來達到停止現成的效果:
public class Hello4 implements Runnable{String name;Boolean isStop;public Hello4(String n){name = n;isStop = false;}public void run(){int i=0;while(!isStop){i++;System.out.println(name+" Hello "+i);}}public void stop()//控制條件{isStop = true;}}
當一個線程對象進入死亡狀態後,就沒有任何方法可以回到其他狀態。
4,暫停線程運行
sleep方法:
yield方法
join方法,
來看join的一個例子:
MotherThread:
package ch22;public class MotherThread implements Runnable{public void run(){System.out.println("媽媽準備煮飯");System.out.println("媽媽發現米酒用完了");System.out.println("媽媽叫兒子去買米酒");Thread son = new Thread(new SonThread());son.start();System.out.println("媽媽等待兒子把米酒買回來");try {son.join();}catch (InterruptedException ie){System.err.println("發生異常!");System.err.println("媽媽中斷煮飯");System.exit(1);}System.out.println("媽媽開始煮飯");System.out.println("媽媽煮好飯了");}}
SonThread:
package ch22;public class SonThread implements Runnable{ public void run(){System.out.println("兒子出門去買米酒");System.out.println("兒子買東西來回需5分鐘");try { for (int i=1; i<=5; i++){Thread.sleep(1000);System.out.print(i+"分鐘 ");}}catch (InterruptedException ie){System.err.println("兒子發生意外");}System.out.println("\n兒子買米酒回來了");}}
Cooking:
package ch22;public class Cooking{public static void main(String argv[]){Thread mother = new Thread(new MotherThread());mother.start();}}
運行結果:
5,資料同步處理
現在我們有這樣一個線程:
package ch22;public class ShareData implements Runnable{int i;public void run(){while (i<10){i++;for(int j=0; j<10000000; j++);System.out.println(Thread.currentThread().getName()+":"+i);}}}
現在我們來產生兩個ShareData對象,並給兩個Thread運行:
package ch22;public class ThreadsExample2{public static void main(String argv[]){ShareData s1 = new ShareData();ShareData s2 = new ShareData();Thread t1 = new Thread(s1);Thread t2 = new Thread(s2);t1.start();t2.start();}}
其結果
可以看到,兩個Thread對象在互動運行,Thread 0和Thread 1分別從0按順序到10.
這是因為兩個Thread共用了程式碼但是沒有共用資料,下面我們來看程式碼和資料都共用的效果:
package ch22;public class ThreadsExample3{public static void main(String argv[]){ShareData s = new ShareData();Thread t1 = new Thread(s);//兩個小成共用一個對象ShareDataThread t2 = new Thread(s);t1.start();t2.start();}}
結果並不是你所想象的從0到10,而是:
這是為什麼呢????
這是因為線程被分割運行了,具體分析略。
6,synchronized實現線程同步
synchronized(要取得鎖的對象)
{
要鎖定的代碼
}
package ch22;public class SyncShareData implements Runnable{int i;public void run(){while (i<10){/*鎖的對象是SyncShareData自己,也就是說這個對象對應的線程要進行同步機制*/synchronized(this){i++;for(int j=0; j<10000000; j++);System.out.println(Thread.currentThread().getName()+":"+i);}}}}
package ch22;public class ThreadsExample4{public static void main(String argv[]){SyncShareData s = new SyncShareData();/*t1和t2都是操作同一個SyncShareData對象的線程, * 要進行同步機制,因為SyncShareData實現了鎖機制*/Thread t1 = new Thread(s);Thread t2 = new Thread(s);t1.start();t2.start();}}
實現了兩個線程對同一個對象操作的同步
7,等待wait與通報notify
生產者和消費者的例子:
package ch22;public class Storage{private int count;//當前庫存值private int size;//最大庫存量public Storage(int s){size = s;}//類裡的方法實現了鎖,則調用這個方法必須取得這個類的對象的鎖public synchronized void addData(String n){while (count == size)//注意為什麼要用while迴圈而不是if{try {this.wait();//進入等待狀態}catch (InterruptedException e) { }}this.notify();//通知消費者可以消費了count++;System.out.println(n+" make data count: "+count);}public synchronized void delData(String n){while (count == 0){try {this.wait();}catch (InterruptedException e) { }}this.notify();System.out.println(n+" use data count: "+count);count--;}}
package ch22;public class Producer extends Thread{private String name;private Storage s;public Producer(String n, Storage s){name = n;this.s = s;}public void run(){while (true){s.addData(name);try {sleep((int)Math.random()*3000);}catch (InterruptedException e) { } }}}
package ch22;public class Consumer extends Thread{private String name;private Storage s;public Consumer(String n, Storage s){name = n;this.s = s;}public void run(){while (true){s.delData(name);try {sleep((int)Math.random()*3000);}catch (InterruptedException e) { } }}}
package ch22;public class ThreadsExample5{public static void main(String argv[]){Storage s = new Storage(3);Producer p1 = new Producer("Producer1", s);Producer p2 = new Producer("Producer2", s);Consumer c1 = new Consumer("Consumer1", s);p1.start();p2.start();c1.start();}}
.........
Producer1 make data count: 3
Consumer1 use data count: 3
Consumer1 use data count: 2
Producer1 make data count: 2
Consumer1 use data count: 2
Producer1 make data count: 2
.........