zoukankan      html  css  js  c++  java
  • 线程八大基础核心五(线程相关方法一)

    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:占有锁对象线程,释放锁并退出执行,线程生命周期结束 

  • 相关阅读:
    页面打印
    scala
    IntelliJ Idea 常用快捷键列表
    flume
    spring事务管理方式,aop
    oldboy es和logstash
    elasticsearch视频34季
    elasticsearch视频
    python3
    git
  • 原文地址:https://www.cnblogs.com/itall/p/12275606.html
Copyright © 2011-2022 走看看