线程通信例子
使用两个线程打印1-100 线程1 线程2 交替打印
线程通信方法
- wait() : 一旦执行此方法,当前线程就会进入阻塞状态,并释放同步监视器。
- notify(): 一般执行此方法,就会唤醒被wait()的一个线程,如果有多个线程被wait.就要唤醒优先级高得线程。
- notifyAll() : 一旦执行此方法,就会唤醒所有被wait的线程。
注意
- wait(),notify(),notifyAll()方法只能出现在同步代码块或同步方法中。
- wait(),notify(),notifyAll()的调用者必须是同步代码块或同步方法中的同步监视器。否则会出现IllegalMonitorStateException异常
- 这三个方法是定义在Object中的
sleep()和wait()的异同
相同
- 一旦执行方法,都可以使得当前线程进入阻塞状态。
不同点
- 方法声明位置不同:Thread类中声明sleep(),Object类中声明wait()
- 调用的要求不同:sleep()可以在任何需要的场景调用。wait()必须使用在同步代码块或同步方法中。
- wait()会释放锁(同步监视器),sleep()不会释放锁。
package demo3;
/**
* @Author GocChin
* @Date 2021/5/11 16:18
* @Blog: itdfq.com
* @QQ: 909256107
* @Descript: 使用两个线程打印1-100 线程1 线程2 交替打印
*/
class Number implements Runnable{
private int number=1;
@Override
public void run() {
while(true){
synchronized (this){ //this就是同步监视器,代表本类的Number
notify();
if (number<=100){
System.out.println(Thread.currentThread().getName()+":"+number);
number++;
//使得调用wait()方法的线程进入阻塞状态。
try {
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();
}
}
生产者/消费者问题
题目:
- 生产者(Productor)将产品交给店员(CLerk),而消费者(Customer)从店员处取走产品,
- 店员一次只能持有固定数量的产品(比如:20),
- 如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产:
- 如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
分析:
- 是否是多线程,是
- 是否共享数据,是
- 如何解决线程安全问题?同步机制
- 是否设计到线程通信,是
/**
* @Author GocChin
* @Date 2021/5/11 16:47
* @Blog: itdfq.com
* @QQ: 909256107
* @Descript: 生产者/消费者问题
* 生产者(Productor)将产品交给店员(CLerk),而消费者(Customer)从店员处取走产品,
* 店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,
* 店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产:如果店中没有产品了,
* 店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
*/
class Clerk {//店员
private int productCount = 0;
//生产产品
public synchronized void produceProduct() {
if (productCount < 20) {
productCount++;
System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品了");
//唤醒消费者
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public synchronized void consumeProduct() {
if (productCount > 0) {
System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品了");
productCount--;
//唤醒生产
notify();
} else {
try {
wait();
} 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(getName() + ":开始生产产品");
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProduct();
}
}
}
class Consumer extends Thread {//消费者
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":开始消费产品");
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.consumeProduct();
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer p1 = new Producer(clerk);
p1.setName("生产者1");
Consumer c1 = new Consumer(clerk);
c1.setName("消费者1");
p1.start();
c1.start();
}
}