zoukankan      html  css  js  c++  java
  • wait(),sleep(),notify(),join()

    wait()注意以下几点:

    1)wait()是属于Object类的方法。

    2)调用了wait()之后会引起当前线程处于等待状态

    3)将当前线程置入“预执行队列”中,并且在wait()所在的代码行处停止执行,直到接到通知或被中断为止。

    4)在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。

    5)执行wait()后,当前线程释放锁;从wait()返回前,线程与其他线程竞争重新获得锁。

    6)如果调用wait()时没有持有适当的锁,则抛出IllegalMonitorStateException异常,它是RuntimeException的一个子类,所以,不需要try-catch语句进行捕捉。

    7)当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException异常。

    8)wait(1000)表示等待1000ms内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

    notify()注意以下几点:

    1)notify()方法可以让该线程重新处于活动(就绪)状态,从而去抢夺锁。

    2)如果多个线程同时处于等待状态,那么调用notify()方法只能随机唤醒一个线程。

    3)在同一时间内,只有一个线程能够获得锁,执行完毕之后,则再将其释放供其它线程抢占。

    notifyAll()就是用来唤醒正在等待状态中的所有线程的:
    (1)notifyAll()只会唤醒那些等待抢占指定对象锁的线程,其他线程则不会被唤醒。
    (2)notifyAll()只会一个一个的唤醒,而并非统一唤醒。因为在同一时间内,只有一个线程能够持有对象锁。
    (3)notifyAll()只是随机的唤醒线程,并非有序唤醒。
     
    注意:执行notify()后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获得该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才可以获取该对象锁。当第一个获得了该对象锁的wait线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,还会继续组赛在wait状态,直到这个对象发出一个notify或notifyAll。
    例子如下:
     1 //当list中的元素达到5个时发出通知notify
     2 public class MyList {
     3     private static List list = new ArrayList();
     4     public static void add() {
     5         list.add("aaa");
     6     }
     7     public static int size() {
     8         return list.size();
     9     }
    10 }
    11 //wait等待线程
    12 public class WaitThread extends Thread{
    13     private Object lock;
    14     public WaitThread(Object lock) {
    15         super();
    16         this.lock = lock;
    17     }
    18     public void run() {
    19         try {
    20             synchronized(lock) {
    21                 if(MyList.size() != 5) {
    22                     System.out.println("wait begin:" + System.currentTimeMillis());
    23                     lock.wait();
    24                     System.out.println("wait end:" + System.currentTimeMillis());
    25                 }
    26             }
    27         } catch(InterruptedException e) {
    28             e.printStackTrace();
    29         }
    30     }
    31 }
    32 //notify通知线程
    33 public class NotifyThread extends Thread{
    34     private Object lock;
    35     public NotifyThread(Object lock) {
    36         super();
    37         this.lock = lock;
    38     }
    39     public void run() {
    40         try {
    41             synchronized(lock) {
    42                 for(int i = 0; i < 10; i++) {
    43                     MyList.add();
    44                     if(MyList.size() == 5) {
    45                         lock.notify();
    46                         System.out.println("已发出通知");
    47                     }
    48                     System.out.println("添加了" + (i + 1) + "个元素!");
    49                     Thread.sleep(1000);
    50                 }
    51             }
    52         } catch (InterruptedException e) {
    53             e.printStackTrace();
    54         }
    55     }
    56 }
    57 //测试线程
    58 public class Main {
    59 
    60     public static void main(String[] args) {
    61         try {
    62             Object lock = new Object();
    63             WaitThread wait = new WaitThread(lock);
    64             wait.start();
    65             Thread.sleep(50);
    66             NotifyThread notify = new NotifyThread(lock);
    67             notify.start();
    68         } catch (InterruptedException e) {
    69             e.printStackTrace();
    70         }
    71     }
    72 
    73 }
    View Code

    运行结果如下:

    notify之后线程继续运行,并没有停止,而是把当前任务执行完后,才把锁由notify线程交给wait线程。

    sleep()方法属于Thread类,从源码给出的解释来看,sleep()方法可以做到如下几点:

    (1)首先,调用sleep()之后,会引起当前执行的线程进入暂时中断状态,也即睡眠状态。

    (2)其次,虽然当前线程进入了睡眠状态,但是依然持有对象锁

    (3)在中断完成之后,自动进入唤醒状态从而继续执行代码【wait(long)也可以实现这个功能】。

    得出如下结论:

    (1)在线程的运行过程中,调用该线程持有对象锁的wait()方法时,该线程首先会进入等待状态,并将自己持有的对象锁释放。

    (2)如果一个线程正处于等待状态时,那么唤醒它的办法就是开启一个新的线程,通过notify()或者notifyAll()的方式去唤醒。当然,需要注意的一点就是,必须是同一个对象锁。

    (3)sleep()方法虽然会使线程中断,但是不会将自己的monitor对象释放,在中断结束后,依然能够保持代码继续执行。

    join()的例子:

     1 public class MyThread extends Thread{
     2     public void run() {
     3         try {
     4             int secondValue = (int) (Math.random() * 10000);
     5             System.out.println(secondValue);
     6             Thread.sleep(secondValue);
     7         } catch(InterruptedException e) {
     8             e.printStackTrace();
     9         }
    10     }
    11 }
    12 public class Main {
    13 
    14     public static void main(String[] args) {
    15         try {
    16             MyThread thread = new MyThread();
    17             thread.start();
    18             thread.join();
    19             System.out.println("mythread对象执行完毕再执行");
    20         } catch(InterruptedException e) {
    21             e.printStackTrace();
    22         }
    23     }
    24 
    25 }
    View Code

    运行结果:

    main线程等待了4476ms才开始执行,也就是等待对象线程执行完毕后才执行。

    join()的作用:使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。能使线程由并行执行转为串行执行,具有同步的效果。

    join与synchronized区别:join在内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监视器”原理做为同步。

    join(long)使用wait(long)来实现,所以是否释放锁,与wait(long)类似。

    查看join的源码如下:

        public final synchronized void join(long millis)
        throws InterruptedException {
            long base = System.currentTimeMillis();
            long now = 0;
    
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
  • 相关阅读:
    Qt应用如何发布
    关于在windows下部署发布QT程序的总结
    干净地发布QT程序
    解析 Qt 程序在Windows 下发布
    Qt 5.2.0 和 VS 2012集成
    Unable to find a qt build, to solve this problem specify a qt build
    运行python程序不显示cmd的方法
    py2exe使用方法
    python 类
    在Pygtk和Glade使用Gtkbuilder
  • 原文地址:https://www.cnblogs.com/cing/p/8622666.html
Copyright © 2011-2022 走看看