两线程交替打印数字的代码:
package com.codeday24.demo02;/**** 线程通信的例子,两个线程交替打印1-100。** 涉及到三个方法:* wait():一旦执行此方法,当前线程进入阻塞状态,并释放同步监视器。* notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级高的* notifyAll():唤醒所有的线程。** 说明:* 1、wait()\notify()\notifyAll()三个方法必须使用在同步代码块或同步方法中;* 2、三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会报异常;* 3、三个方法定义在Object类中。** 面试题:sleep()和wait()的异同?* 1、相同点:一旦执行方法都可以使当前线程进入阻塞状态;* 2、不同点:1)声明的位置不同* 2)调用的要求不同,sleep()可以在任何场景下调用。wait()只能在同步代码块或同步方法总调用;* 3)wait()会释放锁,sleep()不会。**/class Number implements Runnable {private int number = 1;@Overridepublic void run() {while (true) {synchronized (this) {notifyAll();//唤醒线程if (number <= 100) {System.out.println(Thread.currentThread().getName() + ":" + number);number++;try {//使得调用wait方法的线程进入阻塞状态,wait会释放锁wait();} catch (InterruptedException e) {e.printStackTrace();}} else {break;}}}}}public class CommunicationTest {public static void main(String[] args) {Number number = new Number();Thread t1 = new Thread(number);Thread t2 = new Thread(number);t1.setName("线程1");t2.setName("线程2");t1.start();t2.start();}}
注意通信使用的三种方法的作用以及与sleep的区别。
生产者、消费者问题:
同步方法或者同步代码块不一定是在重写的run()方法里面。
package com.codeday24.demo03;/*** 线程通信的应用:经典例题:生产者、消费者例题** 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处* 取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图* 生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通* 知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如* 果店中有产品了再通知消费者来取走产品。** 分析:* 1、是否多线程? Yas,at least two objs.* 2、是否共享数据? 是,产品* 3、如何解决线程的安全问题?同步机制,有三种方法。* 4、是否涉及线程通信?是**/class Clerk {//店员private int productCount = 0;public synchronized void produceProduct() {// 生产if(productCount < 20) {productCount++;System.out.println(Thread.currentThread().getName() + "开始生产第" + productCount + "个产品");notify();}else{System.out.println("货物滞销了!");try {System.out.println("我不进货了,别你妈生产了!");wait();} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void customProduct() {// 消费if(productCount > 0){System.out.println("消费者来买东西了");productCount --;notify();}else{System.out.println("卖光了,滚一边去!");try {wait();System.out.println("好叻,这就滚。");} catch (InterruptedException e) {e.printStackTrace();}}}}class Producer extends Thread {//生产者private Clerk clerk;public Producer(Clerk clerk) {this.clerk = clerk;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "要生产了...");while(true) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}clerk.produceProduct();}}}class Customer extends Thread {//消费者private Clerk clerk;private static int cusCount = 0;public Customer(Clerk clerk) {this.clerk = clerk;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "开始消费...");while(true) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if (cusCount < 100) {clerk.customProduct();cusCount++;System.out.println(Thread.currentThread().getName() + "一共买了" + cusCount + "个产品");}}}}public class ProductTest {public static void main(String[] args) {Clerk clerk = new Clerk();Producer p1 = new Producer(clerk);p1.setName("生产者1");Producer p2 = new Producer(clerk);p1.setName("生产者2");Customer c1 = new Customer(clerk);c1.setName("消费者1");p1.start();c1.start();}}
