一 當多個線程需要協同完成一件事時,可以加鎖+wait,notify一起完成。
1.寫兩個線程,一個線程打印1~52,另一個線程打印A~Z,打印順序是12A34B...5152Z;
思路分析,一個線程打印數字,每次打印兩個數字,26次打印完,另一個線程打印字母,也是26次打印完;可以創建兩個方法,一個方法打印數字,一個打印字母;還有創建一個全局變量用來控制具體執行的是哪個線程;每個方法都被執行26次。
public class TwoThread { public static void main(String args[]){ MyObject1 my = new MyObject1(); new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 26; i++){ my.printNum(); } } }).start(); new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 26; i++){ my.printA(); } } }).start(); } } class MyObject1{ private static boolean flag = true ; public int count = 1; public synchronized void printNum(){ while(flag == false){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print((2*count-1)); System.out.print(2*count); flag = false; this.notify(); } public synchronized void printA(){ while(flag == true){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print((char)(count+'A'-1)); count++; flag = true; this.notify(); } }
2.子線程循環10次,主線程循環100次,然后子線程循環10次,主線程循環100次,這樣循環50次;
思路:跟上面那個一樣,也是synchornized+wait,notify方法;難點在於主線程的啟動不需要start方法,因為程序的入口是main方法,在執行這個程序的時候,主線程已經啟動了;
public class SubMain { public static void main(String args[]){ MyObject2 m = new MyObject2(); new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i<5; i++) m.sub(); } }).start(); for(int i = 0; i<5; i++) m.main1(); } } class MyObject2{ private boolean flag = true;//flag是true時執行sub方法,flag是false時執行main1方法 public synchronized void sub(){ while(flag == false){ //如果flag==false,說明另一個線程擁有該對象的鎖,調用sub的方法被阻塞,直到另一個線程釋放鎖,喚醒該線程。 try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for(int i = 0 ; i<10; i++){ System.out.print("s"); } System.out.println(); flag = false; this.notify(); } public synchronized void main1(){ while(flag == true){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for(int i = 0 ; i<100; i++){ System.out.print("m"); } System.out.println(); flag = true; this.notify(); } }
3.編寫一個程序,啟動三個線程,三個線程的ID分別是A,B,C;,每個線程將自己的ID值在屏幕上打印5遍,打印順序是ABCABC...
public class ThreeThread extends Thread { public static void main(String[] args) { MyObject ob = new MyObject(); new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub for(int i = 0 ; i<10 ; i++) ob.printA(); } }).start(); new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub for(int i = 0 ; i<10 ; i++) ob.printB(); } }).start(); new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub for(int i = 0 ; i<10 ; i++) ob.printC(); } }).start(); } } class MyObject { private int flag = 1; public synchronized void printA(){ while(flag != 1){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print("A"); flag = 2; this.notifyAll(); } public synchronized void printC(){ while(flag != 3){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("C"); flag = 1; this.notifyAll(); } public synchronized void printB(){ while(flag != 2){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print("B"); flag = 3; this.notifyAll(); } }
總結,這3個程序的思路都一樣,都是定義一個對象,將方法都同步,每個方法都用一個線程啟動,對象之間有個全局變量,線程通過全局變量的設置來控制線程執行順序。
