线程八大基础核心五(线程相关方法一)

1.引子

在java多线程并发编程中,有八大基础核心。考考你:
看看都有哪八大基础核心呢?它们分别是:
1.创建线程的方式
2.线程启动
3.线程停止
4.线程生命周期
5.线程相关的方法
6.线程相关的属性
7.线程异常处理
8.线程安全

今天我们从第五个基础核心开始:线程相关方法

2.考考你

#前情回顾
1.在java编程语言中,与线程相关的方法主要有:
1.1.Object.wait/Object.notify/Object/notifyAll
1.2.Thread.sleep/Thread.join/Thread.yield
2.需要把各个方法的作用和使用场景说清楚,需要用两篇文章进行分享

#考考你
1.你知道wait/notify/notifyAll方法的作用吗?
2.你知道notify与notifyAll方法的区别吗?
3.你知道sleep方法的作用吗?
4.你知道wait与sleep方法的区别吗?
5.你知道join方法的作用吗?
6.你知道yield方法的作用吗?

3.案例:wait/notify/notifyAll

方法简述:

wait:释放线程拥有的当前锁对象,让线程进入WAITING状态

notify:唤醒当前锁对象等待池(WaitSet)中,某一个线程

notifyAll:唤醒当前锁对象等待池(WaitSet)中,所有线程

业务描述:

1.通过wait与notify(notifyAll)实现线程协同,实现经典的生产者消费者模式

2.编写生产者,向队列中生产数据,如果队列满,生产者进行等待,并唤醒消费者进行消费

3.编写消费者,从队列中消费数据,如果队列空,消费者进行等待,并唤醒生产者进行生产

4.在主类main方法中,创建两个生产者线程进行生产

5.在主类main方法中,创建一个消费者线程进行消费

生产者:

 1 /**
 2  * 生产者
 3  */
 4 class Producer implements Runnable{
 5
 6     public void run() {
 7         while(true){
 8             synchronized (ProducerConsumerDemo.LOCK){
 9                 // 检查队列是否满,推荐用while而不是if
10                 while(ProducerConsumerDemo.QUEUE.size() ==
11                         ProducerConsumerDemo.CAPACITY){
12                     // 如果队列满,则等待消费者消费
13                     try {
14                         System.out.println("队列满size:" +ProducerConsumerDemo.QUEUE.size()+ ",线程【" +
15                                 Thread.currentThread().getName() + "】正在等待消费者消费.");
16                         ProducerConsumerDemo.LOCK.wait();
17                     } catch (InterruptedException e) {
18                         e.printStackTrace();
19                     }
20                 }
21
22                 // 如果队列不满,则正常生产
23                 ProducerConsumerDemo.QUEUE.add(1);
24                 System.out.println("线程【" + Thread.currentThread().getName() +
25                         "】生产了数据.当前队列size:" + ProducerConsumerDemo.QUEUE.size());
26
27                 // 唤醒消费者
28                 ProducerConsumerDemo.LOCK.notifyAll();
29             }
30         }
31     }
32 }

消费者:

 1 /**
 2  * 消费者
 3  */
 4 class Consumer implements Runnable{
 5
 6     public void run() {
 7         while(true){
 8             synchronized (ProducerConsumerDemo.LOCK){
 9                 // 检查队列是否空,推荐用while而不是if
10                 while(ProducerConsumerDemo.QUEUE.isEmpty()){
11                     // 如果队列空,则等待生产者生产
12                     try {
13                         System.out.println("队列空size:" +ProducerConsumerDemo.QUEUE.size()+ ",线程【" +
14                                 Thread.currentThread().getName() + "】正在等待生产者生产.");
15                         ProducerConsumerDemo.LOCK.wait();
16                     } catch (InterruptedException e) {
17                         e.printStackTrace();
18                     }
19                 }
20
21                 // 如果队列不空,则正常消费
22                 ProducerConsumerDemo.QUEUE.remove(0);
23                 System.out.println("线程【" + Thread.currentThread().getName() +
24                         "】消费了数据.当前队列size:" + ProducerConsumerDemo.QUEUE.size());
25
26                 // 唤醒生产者
27                 ProducerConsumerDemo.LOCK.notifyAll();
28             }
29         }
30     }
31 }

完整代码:

 1 package com.anan.thread.threadmethod;
 2
 3 import java.util.ArrayList;
 4
 5 /**
 6  * 生产者消费者模型:wait与notify(notifyAll)
 7  */
 8 public class ProducerConsumerDemo {
 9
10     // 定义公共资源:队列容量、队列
11     public final static Integer CAPACITY = 6;
12     public final static ArrayList<Integer> QUEUE = new ArrayList<Integer>(CAPACITY);
13
14     // 定义锁对象
15     public final static Object LOCK = new Object();
16
17     public static void main(String[] args) {
18
19         // 创建两个生产者线程
20         Runnable r1 = new Producer();
21         Thread producer0 = new Thread(r1,"producer-0");
22         producer0.start();
23
24         Thread producer1 = new Thread(r1,"producer-1");
25         producer1.start();
26
27         // 创建消费者线程
28         Runnable r2 = new Consumer();
29         Thread consumer1 = new Thread(r2,"consumer-0");
30         consumer1.start();
31
32     }
33 }
34
35 /**
36  * 生产者
37  */
38 class Producer implements Runnable{
39
40     public void run() {
41         while(true){
42             synchronized (ProducerConsumerDemo.LOCK){
43                 // 检查队列是否满,推荐用while而不是if
44                 while(ProducerConsumerDemo.QUEUE.size() ==
45                         ProducerConsumerDemo.CAPACITY){
46                     // 如果队列满,则等待消费者消费
47                     try {
48                         System.out.println("队列满size:" +ProducerConsumerDemo.QUEUE.size()+ ",线程【" +
49                                 Thread.currentThread().getName() + "】正在等待消费者消费.");
50                         ProducerConsumerDemo.LOCK.wait();
51                     } catch (InterruptedException e) {
52                         e.printStackTrace();
53                     }
54                 }
55
56                 // 如果队列不满,则正常生产
57                 ProducerConsumerDemo.QUEUE.add(1);
58                 System.out.println("线程【" + Thread.currentThread().getName() +
59                         "】生产了数据.当前队列size:" + ProducerConsumerDemo.QUEUE.size());
60
61                 // 唤醒消费者
62                 ProducerConsumerDemo.LOCK.notifyAll();
63             }
64         }
65     }
66 }
67
68 /**
69  * 消费者
70  */
71 class Consumer implements Runnable{
72
73     public void run() {
74         while(true){
75             synchronized (ProducerConsumerDemo.LOCK){
76                 // 检查队列是否空,推荐用while而不是if
77                 while(ProducerConsumerDemo.QUEUE.isEmpty()){
78                     // 如果队列空,则等待生产者生产
79                     try {
80                         System.out.println("队列空size:" +ProducerConsumerDemo.QUEUE.size()+ ",线程【" +
81                                 Thread.currentThread().getName() + "】正在等待生产者生产.");
82                         ProducerConsumerDemo.LOCK.wait();
83                     } catch (InterruptedException e) {
84                         e.printStackTrace();
85                     }
86                 }
87
88                 // 如果队列不空,则正常消费
89                 ProducerConsumerDemo.QUEUE.remove(0);
90                 System.out.println("线程【" + Thread.currentThread().getName() +
91                         "】消费了数据.当前队列size:" + ProducerConsumerDemo.QUEUE.size());
92
93                 // 唤醒生产者
94                 ProducerConsumerDemo.LOCK.notifyAll();
95             }
96         }
97     }
98 }

执行结果:

4.讨论分享

#考考你答案
1.你知道wait/notify/notifyAll方法的作用吗?
 1.1.wait/notify/notifyAll都是Object中的方法
 1.2.通过等待与唤醒,实现线程之间的协同
 1.3.wait方法会释放当前锁对象,让线程进入WAITING状态
 1.4.notify方法用于:
  1.4.1.唤醒当前锁对象等待池(WaitSet)中,正在等待
   当前锁对象的某一个线程
  1.4.2.让该线程进入RUNNABLE状态,并移入锁池(EntrySet)中,
  重新竞争锁对象
 1.5.notifyAll方法用于:
  1.5.1.唤醒当前锁对象等待池(WaitSet)中,正在等待
   当前锁对象的所有线程
  1.5.2.让等待当前锁对象的所有线程,进入RUNNABLE状态,并
   移入锁池(EntrySet)中,重新竞争锁对象

2.你知道notify与notifyAll方法的区别吗?
 2.1.通过以上1.4点、1.5点已经说明了notify
 与notifyAll的区别
 2.2.这里可能有朋友不明白锁池(EntrySet),与
 等待池(WaitSet)的概念。我们通过一个图进行说明:

#流程文字描述:
1.锁池(EntrySet):代表正在等待同一锁对象的线程集合,线程进入BLOCKED状态
2.拥有者(Owner):代表已经获取到锁对象的线程
3.等待池(WaitSet):代表已经进入WAITING状态,等待被唤醒的线程集合
4.流程描述:
  4.1.enter:线程准备获取锁对象,此时锁被其它线程占有,线程进入EntrySet
  4.2.acquire:当其它线程释放锁对象,EntrySet中的某个线程获取占有锁对象
  4.3.release:占有锁对象线程,通过wait方式释放锁对象,进入WaitSet中,等待被唤醒
  4.4.acquire:当有其它线程,通过notify/notifyAll方法唤醒WaitSet中线程,线程将重新进入EntrySet,重新竞争获取锁对象
  4.5.release and exit:占有锁对象线程,释放锁并退出执行,线程生命周期结束 

原文地址:https://www.cnblogs.com/itall/p/12275606.html

时间: 2024-10-31 08:42:17

线程八大基础核心五(线程相关方法一)的相关文章

线程八大基础核心一(创建线程的方式)

1.引子 在java多线程并发编程中,有八大基础核心.考考你:看看都有哪八大基础核心呢?它们分别是: 1.创建线程的方式 2.线程启动 3.线程停止 4.线程生命周期 5.线程相关的方法 6.线程相关的属性 7.线程异常处理 8.线程安全 今天我们从第一个基础核心开始:创建线程的方式 2.考考你 #考考你: 你知道在java编程语言中,有几种创建线程的方式吗? #参考如下:网友说法.官方文档 网友说法: 官方文档说法: #说法比较: 在网络上,关于创建线程的方式.主流的说法有四种:继承Threa

线程八大基础核心二(启动线程)

1.引子 在java多线程并发编程中,有八大基础核心.考考你:看看都有哪八大基础核心呢?它们分别是: 1.创建线程的方式 2.线程启动 3.线程停止 4.线程生命周期 5.线程相关的方法 6.线程相关的属性 7.线程异常处理 8.线程安全 今天我们从第二个基础核心开始:启动线程 2.考考你 #前情回顾: 1.在java编程语言中,创建好线程对象后,通过调用start方法,启动线程 Thread t1 = new Thread(); t1.start(); #考考你: 1.问题一:可以调用两次st

线程八大基础核心四(线程生命周期)

1.引子 在java多线程并发编程中,有八大基础核心.考考你:看看都有哪八大基础核心呢?它们分别是: 1.创建线程的方式 2.线程启动 3.线程停止 4.线程生命周期 5.线程相关的方法 6.线程相关的属性 7.线程异常处理 8.线程安全 今天我们从第四个基础核心开始:线程生命周期 2.考考你 #前情回顾: 在java编程语言中,从线程创建,到线程执行结束,会经过一系列状态的转化,称为线程的生命周期 #考考你: 1.你知道线程生命周期中有哪些状态吗? 2.你知道各种状态对应的含义吗? 3.一图胜

线程八大基础核心六(线程属性)

1.引子 在java多线程并发编程中,有八大基础核心.考考你: 看看都有哪八大基础核心呢?它们分别是: 1.创建线程的方式 2.线程启动 3.线程停止 4.线程生命周期 5.线程相关的方法 6.线程相关的属性 7.线程异常处理 8.线程安全 今天我们从第六个基础核心开始:线程相关属性 2.考考你 #前情回顾 在我们日常多线程编程中,需要关心线程的线程优先级有: 线程Id 线程名称 是否是守护线程 线程优先级 #考考你 1.你知道线程Id的作用吗? 2.你知道线程名称的作用吗? 3.你知道什么是守

java核心-多线程(4)-线程类基础知识

1.并发 <1>使用并发的一个重要原因是提高执行效率.由于I/O等情况阻塞,单个任务并不能充分利用CPU时间.所以在单处理器的机器上也应该使用并发. <2>为了实现并发,操作系统层面提供了.但是进程的数量和开销都有限制,并且多个进程之间的数据共享比较麻烦.另一种比较轻量的并发实现是使用线程,一个进程可以包含多个线程.线程在进程中没有数量限制, 数据共享相对简单.线程的支持跟语言是有关系的.Java 语言中支持多线程. <3>Java 中的多线程是抢占式的.这意味着一个任

Android核心基础第五天

一.学习目标及要求 课程目标 课程内容(必须讲的内容,就是讲课的知识点的顺序) * 掌握Activity 配置 * 掌握 Intent 显示意图 * 掌握 Intent 隐式意图 * 掌握两种意图的使用场景 * 掌握 activity 开启的数据传递 * 掌握activity的生命周期 * 掌握横竖屏切换的生命周期 * 掌握不同android版本 生命周期的细微差别 * 掌握开启activity获取返回值 * 掌握请求码 结果码的作用 * 掌握程序入口activity配置参数 * 掌握显示意图 

多线程、并发及线程的基础问题

1)Java 中能创建 volatile 数组吗? 能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组.我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了. 2)volatile 能使得一个非原子操作变成原子操作吗? 一个典型的例子是在类中有一个 long 类型的成员变量.如果你知道该成员变量会被多个线程访问,如计数器.价格等,你最好是将其设置

第二章线程同步基础

Java 7 并发编程实战手册目录 代码下载(https://github.com/Wang-Jun-Chao/java-concurrency) 第二章线程同步基础 2.1简介 多个执行线程共享一个资源的情景,是最常见的并发编程情景之一.在并发应用中常常遇到这样的情景:多个线程读或者写相同的数据,或者访问相同的文件或数据库连接. 为了防止这些共享资源可能出现的错误或数据不一致,我们必须实现一些机制来防止这些错误的发生. 为了解决这些问题,引入了临界区(Critical Section)概念,临

线程池基础篇

一.什么是线程池?为什么要用线程池? 1. 降低资源的消耗.降低线程创建和销毁的资源消耗: 2. 提高响应速度:线程的创建时间为T1,执行时间T2,销毁时间T3,免去T1和T3的时间 3. 提高线程的可管理性. 二.线程池的创建 ThreadPoolExecutor,jdk所有线程池实现的父类 三.参数介绍 先看构造函数: /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters. * *