一 当多个线程需要协同完成一件事时,可以加锁+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个程序的思路都一样,都是定义一个对象,将方法都同步,每个方法都用一个线程启动,对象之间有个全局变量,线程通过全局变量的设置来控制线程执行顺序。