一,概述。
1.什么叫做线程间通信: 在1个进程中,线程往往不是孤立存在的,线程之间需要一些协调通信,来共同完成一件任务。也就是通过一定的方法来实现线程间的“交流”。
因为wait和notify方法定义在Object类中,因此会被所有的类所继承。这些方法都是final的,即它们都是不能被重写的,不能通过子类覆写去改变它们的行为。
1.wait()方法。
语法:锁对象.wait()
特点:wait()方法的调用使得当前线程必须要等待,直到另外一个线程调用notify()或者notifyAll()方法。
wait()方法的调用必须在同步的前提下。(因为该方法是要用锁对象调用,而只有在同步的情况下才有锁)
wait()方法的调用会导致锁的释放。
线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行。要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或synchronized块中。
一个小比较:
当线程调用了wait()方法时,它会释放掉对象的锁。
另一个会导致线程暂停的方法:Thread.sleep(),它会导致线程睡眠指定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的
1 class Bank1 {//公共资源 2 int total=100; 3 } 4 class PresonA implements Runnable{ 5 Bank1 b; 6 //因为要确保两个用户使用的是同一家银行,所以在主函数中new一个银行,然后通过构造函数将这一银行传递给这两个用户 7 public PresonA(Bank1 b){ 8 this.b=b;//将银行的引用传给两个用户 9 } 10 @Override 11 public void run() { 12 while (true){ 13 synchronized (b){//同步代码块,因为要确保两个用户使用的是同一个锁,所以选择银行对象作为锁 14 if(b.total>=0){//打钱,当卡里钱大于0,就唤醒另一个线程来取钱 15 b.notify();//唤醒另一个线程来取钱,注意该方法是要用锁对象调用的 16 try { 17 b.wait();//接着将自己睡眠,然后把锁释放给两一个线程 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 } 22 b.total=b.total+100;//A先存了100 23 System.out.println("A存了100,目前存款为:"+b.total); 24 } 25 } 26 } 27 } 28 class PresonB implements Runnable{ 29 Bank1 b; 30 public PresonB(Bank1 b){ 31 this.b=b; 32 } 33 @Override 34 public void run() { 35 while (true){ 36 synchronized (b){ 37 if(b.total<=0){//取钱,当卡里钱小于0,就唤醒另一个线程来存钱 38 b.notify();//唤醒另一个线程 39 try { 40 b.wait();//将自己睡眠 41 } catch (InterruptedException e) { 42 e.printStackTrace(); 43 } 44 } 45 b.total=b.total-100; 46 System.out.println("****B取了100,目前存款为:"+b.total); 47 } 48 } 49 } 50 } 51 public class CommunicationDemo { 52 public static void main(String[] args) { 53 Bank1 b=new Bank1();//作为公共资源传递给两个用户 54 new Thread(new PresonA(b)).start(); 55 new Thread(new PresonB(b)).start(); 56 } 57 }
运行结果:
为什么两个线程的时候执行结果正确而四个线程的时候就不对了呢?
因为线程在wait()的时候,接收到其他线程的通知,即往下执行,不再进行判断。
两个线程的情况下,唤醒的肯定是另一个线程;但是在多个线程的情况下,就是随机唤醒,所以执行结果就会混乱无序。
比如,一个可能的情况是,一个增加线程执行的时候,其他两个线程都在wait,这时候第一个线程调用了notify()方法,其他线程中的一个将被唤醒,然后执行各自的增加或减少方法。
解决的方法就是:就是让各个新城在被唤醒之后仍然进行条件判断
来源:https://www.cnblogs.com/ljl150/p/12389548.html