wait和notify

Posted qwangxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了wait和notify相关的知识,希望对你有一定的参考价值。

一.wait和notify

wait是让线程进入等待状态

notify是随即唤醒一个等待中的线程并释放锁(在执行完整个同步代码块后)

notifyAll是唤醒所有等待的线程

example:

开启两个线程A和B 先打印五遍线程B再打印五遍线程A

[java] view plain copy
 
  1. class ABRunnable implements Runnable {  
  2.     //声明一个标记来解决A先进来的问题  
  3.     private boolean flag = false;  
  4.     // 声明一把锁  
  5.     private Object object = new Object();  
  6.     @Override  
  7.     public void run() {  
  8.         // 循环打印AB 并打印线程名字  
  9.         String name = Thread.currentThread().getName();  
  10.         System.out.println(name + "进来了");  
  11.         //加同步锁  
  12.         //运行结果很随机 有时会卡住  
  13.         //A先进来会卡住 B先进来运行正确  
  14.         synchronized (object) {  
  15.             if (name.equals("线程B") && !flag) {  
  16.                 //进入等待  
  17.                 try {  
  18.                     //如果B线程等待时 还拿着锁的话 会有什么现象  
  19.                     //当线程进入等待的时候会释放锁  
  20.                     //在哪个位置等待的 就从哪个位置被唤醒  
  21.                     object.wait();  
  22.                 } catch (InterruptedException e) {  
  23.                     // TODO Auto-generated catch block  
  24.                     e.printStackTrace();  
  25.                 }  
  26.                 for (int i = 0; i < 5; i++) {  
  27.                     System.out.println(name);  
  28.                 }  
  29.             }  
  30.             for (int i = 0; i < 5; i++) {  
  31.                 System.out.println(name);  
  32.             }  
  33.             //如果线程A打印完了 线程B就不需要再等待了 直接打印就行  
  34.             if (name.equals("线程A")) {  
  35.                 flag = true;  
  36.             }  
  37.             object.notify();  
  38.         }  
  39.     }  
  40. }  

创建线程并开启

[java] view plain copy
 
  1. public static void main(String[] args) {  
  2.         ABRunnable runnable = new ABRunnable();  
  3.         Thread t1 = new Thread(runnable, "线程A");  
  4.         Thread t2 = new Thread(runnable, "线程B");  
  5.         t1.start();  
  6.         t2.start();  
  7. }  

单例饿汉式:如何保证多个线程调用时的安全性以及如何提高效率

[java] view plain copy
 
  1. class HungryMan {  
  2.     // 延迟加载(等调用方法的时候在创建对象)  
  3.     private static HungryMan hungryMan = null;  
  4.   
  5.     // 私有化构造方法(不让外界创建对象 对象由自己创建)  
  6.     private HungryMan() {  
  7.         // TODO Auto-generated constructor stub  
  8.     }  
  9.   
  10.     public static HungryMan getInstance() {  
  11.         try {  
  12.             Thread.sleep(1000);  
  13.         } catch (InterruptedException e) {  
  14.             // TODO Auto-generated catch block  
  15.             e.printStackTrace();  
  16.         }  
  17.         // 在多线程程序中 这个单例安全吗 为什么  
  18.         // 例如多个线程 调用该方法  
  19.         // 加锁来保证同一时间只有一个线程来创建对象  
  20.         //提高效率  
  21.         if (hungryMan == null) {  
  22.             synchronized (HungryMan.class) {  
  23.                     hungryMan = new HungryMan();  
  24.             }  
  25.         }  
  26.         return hungryMan;  
  27.     }  
  28. }  
  29. class HungryRunnable implements Runnable{  
  30.   
  31.     @Override  
  32.     public void run() {  
  33.         // TODO Auto-generated method stub  
  34.         while (true) {  
  35.             HungryMan hungryMan = HungryMan.getInstance();  
  36.             System.out.println(hungryMan);  
  37.         }  
  38.     }  
  39.       
  40. }  

join方法:  哪个线程调用了这个方法 就会拿到CPU的执行权 先完成执行

setDeamon: (守护线程)该方法必须在线程启动前调用 在主线程结束时结束

(并不是立即结束 需要一个缓冲时间)

example:

开启子线程循环打印十次 主线程循环打印十次 先打印子线程再打印主线程

[java] view plain copy
 
  1. class SonRunnable implements Runnable{  
  2.   
  3.     @Override  
  4.     public void run() {  
  5.         for (int i = 0; i < 10; i++) {  
  6.             System.out.println(Thread.currentThread().getName());  
  7.         }     
  8.     }  
  9. }class TestRunnable implements Runnable{  
  10.   
  11.     @Override  
  12.     public void run() {  
  13.         // TODO Auto-generated method stub  
  14.         while (true) {  
  15.               
  16.             System.out.println("测试");  
  17.         }  
  18.       

主线程:

[java] view plain copy
 
  1. public static void main(String[] args) {  
  2.         TestRunnable testRunnable = new TestRunnable();  
  3.         Thread t2 = new Thread(testRunnable);  
  4.         //该方法必须在线程启动前调用  
  5.         t2.setDaemon(true);  
  6.         t2.start();  
  7.         SonRunnable sr = new SonRunnable();  
  8.         Thread t1 = new Thread(sr);   
  9.         t1.start();  
  10.         //哪个线程调用了这个方法 就会拿到CPU的执行权  
  11.         //先完成执行   
  12.         try {  
  13.             t1.join();  
  14.         } catch (InterruptedException e) {  
  15.             // TODO Auto-generated catch block  
  16.             e.printStackTrace();  
  17.         }  
  18.         for (int i = 0; i <www.leyouzaixian2.com 10; i++) {  
  19.             System.out.println(Thread.currentThread().getName());  
  20.         }  
  21.           
  22.         System.out.println("主线程结束了");  
  23. }  

二.接口回调

写法:

1.创建一个接口

2.写一个功能类(打印字符串的方法的参数 可以使用借口来接收 达到调用接口中方法的目的)

3.写实现类

example:

键盘输入1或2 输入1的时候打印红色的字 输入2的时候打印黑色的字

 

System.err.println("哈哈"); 打印的是红色的

 

System.out.println("呵呵"); 打印的是黑色的


创建接口:

[java] view plain copy
 
  1. //接口  
  2. interface PrintInter{  
  3.     //打印方法  
  4.     public abstract void print(String string);  
  5. }  
  6. class PrintClass{  
  7.     //打印方法(接收接口的参数)  
  8.     public static void www.hjha178.com/ printString(PrintInter inter) {  
  9.         //调用接口中的方法  
  10.         inter.print("接口回调");  
  11.     }  
  12. }  

写实现类:

[java] view plain copy
 
  1. class PrintRed implements PrintInter{  
  2.   
  3.     @Override  
  4.     public void print(String string) {  
  5.         System.err.println(string);  
  6.     }  
  7.       
  8. }  
  9. class PrintBlack implements PrintInter{  
  10.   
  11.     @Override  
  12.     public void print(String string) {  
  13.         System.out.println(string);  
  14.     }  
  15.       
  16. }  

或者直接在main函数中写匿名内部类:

[java] view plain copy
 
    1. public static void main(String[] args) www.chuangshi88.cn/{  
    2.         System.out.println("请输入 1 或 2 ");  
    3.         Scanner scanner = new Scanner(System.in);  
    4.         String string = scanner.nextLine();  
    5.         PrintInter inter = null;  
    6.         if (string.equals("www.douniu1956.com/1")) {  
    7.             PrintClass.printString(new PrintInter() {  
    8.                 @Override  
    9.                 public void print(String string) {  
    10.                     System.err.println(string);  
    11.                 }  
    12.             });  
    13.         }else {  
    14.             PrintClass.printString(new PrintInter() {  
    15.                 @Override  
    16.                 public void print(String www.yongshiyule178.com string) {  
    17.                     System.out.println(string);  
    18.                 }  
    19.             });  
    20.         }  
    21.         //调用功能类方法  
    22.         PrintClass.printString(inter);  
    23.     }  

以上是关于wait和notify的主要内容,如果未能解决你的问题,请参考以下文章

阿里中间件技术:消息中间件篇

线程中wait 和sleep 的区别

sleep与 wait区别

JAVA-sleep和wait的区别

sleep()和wait()有啥区别

wait方法和sleep方法的区别