两线程交替打印数字的代码:
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;
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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();
}
}