Java多线程(案例+解析)中级部分:线程的通信(1)

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+“:”+number);

number++;

try {

//使得调用如下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();

}

}

在这里插入图片描述

(一) 涉及到线程通信当中的三个方法:(只能出现在同步代码块和同步方法当中)

(1) wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。

(2) notify():一旦执行此方法,就会唤醒被wait()的一个线程。

如果有多个线程被wait(),就唤醒优先级别高的那个。

(3) notifyAll():一旦执行此方法,就会唤醒所有被wait()的一个线程。

(二) 说明:

(1) wait(),notify(),notifyAll()这三个方法必须使用在同步代码块或者同步方法当中,并且是this对象调用的

在这里插入图片描述

2、任意对象做为同步监视器(定义Object对象)

(1) wait(),notify(),notifyAll()这三个方法的调用者必须是同步代码块或者同步方法当中的同步监视器

否则,会出现IllegalMonitorStateException异常

(2) wait(),notify(),notifyAll()这3个方法是定义在java.lang.Object类当中的

package com.itzheng.java2;

/*

线程通信的例子:使用两个线程打印1-100。线程1,线程2,交替打印

*/

class Number implements Runnable{

private int number = 1;

private Object obj = new Object();

@Override

public void run() {

while (true){

synchronized (obj){

obj.notify();//唤醒等待的(wait)的线程

if(number <= 100){

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+“:”+number);

number++;

try {

//使得调用如下wait()方法的线程进入阻塞状态

obj.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();

}

}

二、多线程重点难点总结


1、sleep()和wait()的异同?
(1)相同点:一旦执行方法都可以使得当前线程进入阻塞状态。
(2)不同点:

1)两个方法声明的位置不同:Thread类当中声明sleep() ,Object类当中声明wait()

2)调用的要求不同:sleep()可以在任何需要的场景下调用。wait()必须使用在同步代码块或同步方法当中

3)关于是否释放同步监视器的问题:如果两个方法都使用在同步代码块或同步方法当中,sleep()方法不会释放锁,wait()会释放锁。

三、例题二:生产者和消费者问题(线程通信的应用)


●生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处

取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图

生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通

知生产者继续生产:如果店中没有产品了,店员会告诉消费者等- - 下,如

果店中有产品了再通知消费者来取走产品。

●这里可能出现两个问题:

➢生产者比消费者快时,消费者会漏掉一.些数据没有取到。

➢消费者比生产者快时,消费者会取相同的数据。

代码实现:例题(生产者/消费者问题)

package com.itzheng.java2;

/*

线程通信的应用:金典例题:生产者/消费者问题

取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图

生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通

知生产者继续生产:如果店中没有产品了,店员会告诉消费者等- - 下,如

果店中有产品了再通知消费者来取走产品。

分析:

1、是否是多线程的问题?是,生产者线程,消费者线程

2、是否共享数据的问题?是,店员(或产品)

3、如何来解决线程的安全问题?同步机制,有三种方法

4、是否涉及到线程的通信?是

创建Clerk办事情的对象,作为同步监视器

创建Producer:生产者

创建Consumer:消费者

分别调用对应的start方法

两个线程分别调用Clerk当中的方法,同步监视器就是Clerk对象,只有当生产完毕后才可以执行消费

*/

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) {

最后

这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档

祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!

感谢大家的支持!!

image.png

productCount++;

System.out.println(Thread.currentThread().getName() + “:开始生产第” + productCount + “个产品”);

notify();//唤醒线程

}else{

//等待

try {

wait();

} catch (InterruptedException e) {

最后

这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档

祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!

感谢大家的支持!!

[外链图片转存中…(img-CnXFrjUJ-1714355208457)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值