线程间的共享和协作

synchronized

        synchronized是内置锁,分为对象锁和类锁。可以用于方法,代码块中。如果是方法,锁的是this对象,如果是代码块,锁的是指定的那个对象。类锁其实是一个不太准确的说法,应用于静态方法,本质上锁的是该Class对象

等待和通知的标准范式

等待方

  1. 获取对象锁
  2. 检查条件,条件不满足,调用对象wait
  3. 执行业务代码

synchronized(对象){

         while(不满足条件){

         对象.wait();

}                

//执行业务代码

}

通知方

  1. 获取对象锁
  2. 修改条件
  3. 发出通知

synchronized(对象){

         执行业务代码,修改条件

         调用对象的notify/notifyAll,发出通知

}

注意:

wait调用之后,会立刻释放锁。

notify/notifyAll不会马上释放锁,会等到synchronized(对象){}代码块执行结束,才会释放锁。

notify只会通知一个线程,如果多个线程wait,那么用notifyAll。

Thread.yield和Thread.sleep,不会释放锁

实战生产消费者模型

wait/notifyAll

/**

 * 快递公里数和地点变化通知

 */

public class Express {

         private int km = 0; //公里数

         private String site = "BeiJing"; //地点


         //发出公里数发生变化的通知

         public synchronized void changeKm(int km) {

                   this.km = km;

                   notifyAll();

         }


         //发出地点发生变化的通知

         public synchronized void changeSite(String site) {

                   this.site = site;

                   notifyAll();

         }

         public synchronized void waitKm() {

                   while (this.km <= 10) {

                            try {

                                     wait();

                                     System.out.println(Thread.currentThread().getName() + " km notify");

                            } catch (InterruptedException e) {

                                     e.printStackTrace();

                            }

                   }

                   System.out.println(Thread.currentThread().getName() + " km change");

         }

         public synchronized void waitSite() {

                   while (this.site.equals("BeiJing")) {

                            try {

                                     wait();

                                     System.out.println(Thread.currentThread().getName() + " site notify");

                            } catch (InterruptedException e) {

                                     e.printStackTrace();

                            }

                   }

                   System.out.println(Thread.currentThread().getName() + " site change");

         }

         public static void main(String[] args) throws InterruptedException {

                   Express express = new Express();

                   //三个等待公里数变化的线程

                   for (int i = 0; i < 3; i ++) {

                            Thread thread = new Thread("thread km - " + i) {

                                     @Override

                                     public void run() {

                                               express.waitKm();

                                     }

                            };

                            thread.start();

                   }

                   //三个等待地点变化的线程

                   for (int i = 0; i < 3; i ++) {

                            Thread thread = new Thread("thread site - " + i) {

                                     @Override

                                     public void run() {

                                               express.waitSite();

                                     }

                            };

                            thread.start();

                   }

                   Thread.sleep(1000);

                   express.changeKm(100);

//               express.changeSite("shagnhai");

         }
}

Lock/Condition

public class ExpressLock {

         private int km = 0;

         private String site = "Beijing";

         private Lock lock = new ReentrantLock();

         private Condition kmCondition = lock.newCondition();

         private Condition siteCondition = lock.newCondition();


         public void changeKm() {

                   try {

                            lock.lock();

                            km = 100;

                            kmCondition.signalAll();

                   }finally {

                            lock.unlock();

                   }

         }

         public void changeSite() {

                   try {

                            lock.lock();

                            site = "ShangHai";

                            siteCondition.signalAll();

                   }finally {

                            lock.unlock();

                   }

         }


         public void waitKm() {

                   try {

                            lock.lock();

                            while (km <= 0) {

                                     kmCondition.await();

                                     System.out.println(Thread.currentThread().getName() + " km notify");

                            }

                   } catch (InterruptedException e) {

                            e.printStackTrace();

                   } finally {

                            lock.unlock();

                   }

                   System.out.println(Thread.currentThread().getName() + " km change");

         }


         public void waitSite() {

                   try {

                            lock.lock();

                            while (site.equals("Beijing")) {

                                     siteCondition.await();

                                     System.out.println(Thread.currentThread().getName() + " site notify");

                            }

                   } catch (InterruptedException e) {

                            e.printStackTrace();

                   } finally {

                            lock.unlock();

                   }

                   System.out.println(Thread.currentThread().getName() + " site change");

         }

         public static void main(String[] args) {

                   ExpressLock expressLock = new ExpressLock();



                   //等待公里数变化的线程

                   for (int i = 0; i < 3; i ++) {

                            Thread thread = new Thread() {

                                     @Override

                                     public void run() {

                                               expressLock.waitKm();

                                     }

                            };

                            thread.start();

                   }

                   //等到地点变化的线程

                   for (int i = 0; i < 3; i ++) {

                            Thread thread = new Thread() {

                                     @Override

                                     public void run() {

                                               expressLock.waitSite();

                                     }

                            };

                            thread.start();

                   }


                   try {

                            Thread.sleep(1000);

                   } catch (InterruptedException e) {

                            e.printStackTrace();

                   }

                   expressLock.changeKm();

                   expressLock.changeSite();

         }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值