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();
 }
}

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