zoukankan      html  css  js  c++  java
  • 并发编程学习笔记(五、线程中常用的方法)

    目录:

    • sleep()
    • wait()
    • notify()/notifyAll()
    • yieid()
    • join()
    • 总结

    sleep():

    1、sleep()方法的作用是让线程暂停指定的毫秒数

    2、sleep()方法只是暂时交出CPU的执行权并非释放锁

    3、sleep()方法不需要在synchronize块中执行,而wait()方法需要

    4、sleep()可以通过interrupt()方法打断休眠状态。

    5、sleep()只是操作线程,并不涉及线程间的通信

     1 public class SleepTest {
     2     /**
     3      * sleep()方法不会释放锁,因此线程是按照先后顺序执行的
     4      */
     5     public synchronized void sleepMethod() {
     6         System.out.println("Sleep start : " + Thread.currentThread().getName());
     7         try {
     8             Thread.sleep(1000);
     9         } catch (InterruptedException e) {
    10             e.printStackTrace();
    11         }
    12         System.out.println("Sleep end : " + Thread.currentThread().getName());
    13     }
    14 
    15     /**
    16      * wait()方法会释放锁,因此一旦调用wait()方法就会造成其他线程运行
    17      */
    18     public synchronized void waitMethod() {
    19         System.out.println("Wait start : " + Thread.currentThread().getName());
    20         synchronized (this) {
    21             try {
    22                 wait(1000);
    23             } catch (InterruptedException e) {
    24                 e.printStackTrace();
    25             }
    26         }
    27         System.out.println("Wait end :" + Thread.currentThread().getName());
    28     }
    29 
    30     public static void main(String[] args) {
    31         final SleepTest test1 = new SleepTest();
    32         for (int i = 0; i < 5; i++) {
    33             new Thread(test1::sleepMethod).start();
    34         }
    35 
    36         try {
    37             //暂停十秒,等上面程序执行完成
    38             Thread.sleep(10000);
    39         } catch (InterruptedException e) {
    40             e.printStackTrace();
    41         }
    42 
    43         System.out.println("-----分割线-----");
    44 
    45         final SleepTest test2 = new SleepTest();
    46         for (int i = 0; i < 5; i++) {
    47             new Thread(test2::waitMethod).start();
    48         }
    49     }
    50 }

    sleep都是一个一个执行完,先start再end,从这一现象便知sleep()方法并不会释放锁;而wait则不会交出CPU的执行权。

    若将18、20行的synchronize删除,wait()方法便会抛出IllegalMonitorStateException异常,所以wait()方法必须要在synchronize块或synchronize方法中执行。

    wait():

    1、wait()、notify()方法通常成对出现

    2、wait()、notify()方法都需要在synchronize块或synchronize方法中执行

    3、wait()方法可以通过interrupt()方法打断暂停状态

    4、通过为wait()方法设置时间(wait(1000))或调用notify()方法可以让对象重新获取锁

    notify()、notifyAll():

    1、notify()用来唤醒此对象上等待的单个线程,notifyAll()唤醒多个线程

    2、notifyAll()唤醒的顺序为先进后出(类似于栈),Last In First Out。

    3、wait()、notify()、notifyAll()涉及线程间的通信。

     1 public class WaitClassDemo {
     2 
     3     private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
     4 
     5     public static void main(String[] args) {
     6         Object obj = new Object();
     7         for (int i = 0; i < 5; i++) {
     8             new WaitThread(i + "", obj).start();
     9         }
    10         new NotifyThread(obj).start();
    11     }
    12 
    13     /**
    14      * 调用wait()方法的线程
    15      */
    16     static class WaitThread extends Thread {
    17         Object obj;
    18         public WaitThread(String name, Object obj) {
    19             setName("WaitThread" + name);
    20             this.obj = obj;
    21         }
    22 
    23         @Override
    24         public void run() {
    25             synchronized (obj) {
    26                 System.out.println(sdf.format(new Date()) + " " + getName() + " before wait()");
    27                 try {
    28                     obj.wait();
    29                 } catch (InterruptedException e) {
    30                     e.printStackTrace();
    31                 }
    32                 System.out.println(sdf.format(new Date()) + " " + getName() + " after wait()");
    33             }
    34         }
    35     }
    36 
    37     /**
    38      * 调用notify()/notifyAll()
    39      */
    40     static class NotifyThread extends Thread {
    41         Object obj;
    42         public NotifyThread(Object obj) {
    43             setName("NotifyThread");
    44             this.obj = obj;
    45         }
    46 
    47         @Override
    48         public void run() {
    49             synchronized (obj) {
    50                 try {
    51                     Thread.sleep(5000);
    52                 } catch (InterruptedException e) {
    53                     e.printStackTrace();
    54                 }
    55                 System.out.println(sdf.format(new Date()) + " NotifyThread before notify()");
    56                 // 唤醒所有线程 用notifyAll()会按照后进先出(LIFO)的原则恢复线程
    57                 obj.notifyAll();
    58                 try {
    59                     Thread.sleep(5000);
    60                 } catch (InterruptedException e) {
    61                     e.printStackTrace();
    62                 }
    63                 System.out.println(sdf.format(new Date()) + " NotifyThread after notify()");
    64             }
    65         }
    66     }
    67 }

    yieId():

    1、作用:告诉CPU你这次分给我的资源我不要了,你去给其它线程吧( ̄︶ ̄)↗

    2、注意:

    • yieId()方法不能保证其它线程一定能够执行,因为它仍是可执行状态,所以仍有可能被CPU再次执行。
    • 执行yieId()方法不会释放锁

    join():

    1、作用:让一个线程在另一个线程执行完后再执行

    2、注意:线程A内部执行线程B的join()方法,那么A将会阻塞,直到线程B执行完后才会执行线程A。

    3、Demo:小明点了一个煎饼果子,老板收到订单后便开始做煎饼;那小明肯定是不可能在煎饼果子来之前啥事都不做,老板也一样;所以我们这里用线程来实现他们两个的动作。

     1 public class Consumer {
     2 
     3     public void eat() {
     4         System.err.println("开始吃煎饼果子...");
     5         try {
     6             Thread.sleep(1000);
     7         } catch (InterruptedException e) {
     8             e.printStackTrace();
     9         }
    10         System.err.println("煎饼果子吃完啦...");
    11     }
    12 }
     1 public class Producer {
     2 
     3     public void manufacture() {
     4         System.out.println("开始制作煎饼果子...");
     5         try {
     6             Thread.sleep(1000);
     7         } catch (InterruptedException e) {
     8             e.printStackTrace();
     9         }
    10         System.out.println("煎饼果子制作完成...");
    11     }
    12 }
     1 public class JoinTest {
     2 
     3     public static void main(String[] args) {
     4         Thread producerThread = new Thread(() -> {
     5             Producer producer = new Producer();
     6             producer.manufacture();
     7         });
     8         producerThread.start();
     9 
    10         Thread consumerThread = new Thread(() -> {
    11             try {
    12                 producerThread.join();
    13             } catch (InterruptedException e) {
    14                 e.printStackTrace();
    15             }
    16             Consumer consumer = new Consumer();
    17             consumer.eat();
    18         });
    19         consumerThread.start();
    20     }
    21 }

    总结:

    1、方法调用:sleep()、yieId()都是Thread类的静态方法;join()是Thread类的实例方法;wait()、notify()、notifyAll()是Object类的实例方法。

    2、释放锁:Thread.sleep()、Thread.yieId()不会释放锁;wait()会释放锁。

    3、执行位置:sleep()、yieId()、join()不一定需要在synchronize块中执行;wait()、notify()、notifyAll()需要在synchronize块中执行,否则会抛出IllegalMonitorStateException。

  • 相关阅读:
    [Swift系列]002-基础语法
    [Swift系列]001-入门准备
    navicat连接服务器Mysql 忘记密码 ------- 查看密码
    Elasticsearch 7.10.1 尝鲜笔记
    java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy 排查解决
    nginx TCP 代理& windows傻瓜式安装
    python项目出现的问题 Microsoft Visual C++ 14.0 is required解决方法
    前端使用crypto.js进行加密
    xcopy 高级使用
    高并发解决方案-概念知识
  • 原文地址:https://www.cnblogs.com/bzfsdr/p/11568253.html
Copyright © 2011-2022 走看看