java基礎---線程二


學習筆記 -  線程間通信

一、線程間通信示例一

/**
 * 線程間通訊: 其實就是多個線程在操作同一個資源 但是操作的動作不同
 *
 * 安全問題:
 * 1.同步裏面必須有兩個線程
 * 2.必須用同一個鎖
 *
 * @author Administrator
 *
 */
/**
 * wait:
 * notify()
 * notifyAll();
 *
 * 都使用在同步中,因爲要對持有監視器(鎖)的線程操作
 * 所以要使用在同步中,因爲只有同步才具有鎖。
 *
 * 爲什麼這些操作線程的方法要定義Object類中?
 * 因爲這些方法在操作同步中線程時,都必須要表示他們所操作線程只有的鎖。
 * 只有同一個鎖上的被等待線程,可以被同一個鎖上notify喚醒
 * 不可以對不同鎖中的線程進行喚醒。
 *
 * 也就是說,等待和喚醒必須是同一個鎖。
 * 而鎖可以是任意對象,所以可以被任意調用的方法定義在Object中。

 

public class InputOutputDemo {

 public static void main(String[] args) {
  Res r = new Res();
  
  Input in = new Input(r);
  Output out = new Output(r);
  
  Thread t1 = new Thread(in);
  Thread t2 = new Thread(out);
  
  t1.start();
  t2.start();

 }

}

class Input implements Runnable {
 private Res r;
//  Object obj = new Object();

 Input(Res r) {
  this.r = r;
 }

 @Override
 public void run() {
  int x = 0;
  while (true) {
   //能夠成功輸出的方法:使用單一的字節碼  : Input.class Output.class Res.class r
   //使用  Object obj = new Object()  不行,原因:不是同一份字節碼
   //this 也不行,this 是指當前類的字節碼,所以也是錯誤的
   
   synchronized (r) {
    //flag爲false,不執行wait()
    //第二次,爲true,執行賦值操作
    if(r.flag)
     try {
      r.wait();
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
   
   if (x == 0) {
    r.name = "mike";
    r.sex = "man";
   } else {
    r.name = "lise";
    r.sex = "woman";
   }

   x = (x + 1) % 2;
   //flag 變爲true 同時喚醒下面的線程
   r.flag = true;
   r.notify();
   }
  }
 }
}

class Output implements Runnable {
 private Res r;
 //Object obj = new Object();
 Output(Res r) {
  this.r = r;
 }
 @Override
 public void run() {
  while (true) {
   synchronized (r) {
    //爲fasle 等待
    //同樣第二次爲true,執行打印操作
    if(!r.flag)
     try {
      r.wait();
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    System.out.println(r.name + "........" + r.sex);
    //爲true喚醒上面的線程
    r.flag = true;
    r.notify();
   }
   
  }

 }

}
class Res {
 String name;
 String sex;
 boolean flag = false;
}

 

二、線程間通信示例二

/**
 * 線程間通訊: 其實就是多個線程在操作同一個資源 但是操作的動作不同
 *
 * 安全問題:
 * 1.同步裏面必須有兩個線程
 * 2.必須用同一個鎖
 *
 * @author Administrator
 *
 */
/**
 * wait: notify() notifyAll();
 *
 * 都使用在同步中,因爲要對持有監視器(鎖)的線程操作 所以要使用在同步中,因爲只有同步才具有鎖。
 *
 * 爲什麼這些操作線程的方法要定義Object類中? 因爲這些方法在操作同步中線程時,都必須要表示他們所操作線程只有的鎖。
 * 只有同一個鎖上的被等待線程,可以被同一個鎖上notify喚醒 不可以對不同鎖中的線程進行喚醒。
 *
 * 也就是說,等待和喚醒必須是同一個鎖。 而鎖可以是任意對象,所以可以被任意調用的方法定義在Object中。

public class InputOutputDemo2 {

 public static void main(String[] args) {
  Res2 r = new Res2();

  Input2 in = new Input2(r);
  Output2 out = new Output2(r);

  Thread t1 = new Thread(in);
  Thread t2 = new Thread(out);

  t1.start();
  t2.start();

 }

}

class Input2 implements Runnable {
 private Res2 r;

 // Object obj = new Object();

 Input2(Res2 r) {
  this.r = r;
 }

 @Override
 public void run() {
  int x = 0;
  while (true) {
   // 能夠成功輸出的方法:使用單一的字節碼 : Input.class Output.class Res.class r
   // 使用 Object obj = new Object() 不行,原因:不是同一份字節碼
   // this 也不行,this 是指當前類的字節碼,所以也是錯誤的

   synchronized (r) {
    // flag爲false,不執行wait()
    // 第二次,爲true,執行賦值操作
    if (x == 0)
     r.set("111111", "man");
    else
     r.set("wang", "woman");
    x = (x + 1) % 2;

   }
  }

 }

}

class Output2 implements Runnable {
 private Res2 r;

 // Object obj = new Object();
 Output2(Res2 r) {
  this.r = r;
 }

 @Override
 public void run() {
  while (true) {
   synchronized (r) {
    r.out();
   }

  }

 }

}

class Res2 {
 private String name;
 private String sex;
 boolean flag = false;
 public synchronized void set(String name, String sex) {
  if (flag)
   try {
    wait();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  this.name = name;
  this.sex = sex;
  flag = true;
  notify();
 }
 public synchronized void out() {
  if (!flag)
   try {
    wait();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  System.out.println("name" + "......." + name + "--" + "sex"
    + "........." + sex);
  flag = false;
  notify();
 }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章