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。

  • 相关阅读:
    array_map()与array_shift()搭配使用 PK array_column()函数
    Educational Codeforces Round 8 D. Magic Numbers
    hdu 1171 Big Event in HDU
    hdu 2844 poj 1742 Coins
    hdu 3591 The trouble of Xiaoqian
    hdu 2079 选课时间
    hdu 2191 珍惜现在,感恩生活 多重背包入门题
    hdu 5429 Geometric Progression 高精度浮点数(java版本)
    【BZOJ】1002: [FJOI2007]轮状病毒 递推+高精度
    hdu::1002 A + B Problem II
  • 原文地址:https://www.cnblogs.com/bzfsdr/p/11568253.html
Copyright © 2011-2022 走看看