Wait和sleep的區(qū)別

wait方法是Object里面的一個native方法,而sleep是Thread里面的方法,下面分別來看兩個方法的源碼:

/**
     * Causes the current thread to wait until another thread invokes the
     * {@link java.lang.Object#notify()} method or the
     * {@link java.lang.Object#notifyAll()} method for this object.
     * In other words, this method behaves exactly as if it simply
     * performs the call {@code wait(0)}.
     * <p>
     * The current thread must own this object's monitor. The thread
     * releases ownership of this monitor and waits until another thread
     * notifies threads waiting on this object's monitor to wake up
     * either through a call to the {@code notify} method or the
     * {@code notifyAll} method. The thread then waits until it can
     * re-obtain ownership of the monitor and resumes execution.
     * This method should only be called by a thread that is the owner
     * of this object's monitor. See the {@code notify} method for a
     * description of the ways in which a thread can become the owner of
     * a monitor.
      *This method should only be called by a thread that is the owner
     * of this object's monitor. See the {@code notify} method for a
     * description of the ways in which a thread can become the owner of
     * a monitor.
     *
**/
public final native void wait() throws InterruptedException;

從官方的注釋可以知道,當(dāng)前線程對要持有當(dāng)前對象的資源鎖,并且當(dāng)前線程會釋放鎖。
而且要調(diào)用notify喚醒wait的線程時,必須先持有對象的資源鎖,從這里可以知道,不管是調(diào)用wait或者
notify,都要持有同一個對象的鎖。

public void funcWait() {
    synchronized(obj) {
        obj.wait()
}
}

public void funcNotify() {
    synchronized(obj) {
        obj.notify()
}
}

Sleep

    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public static void sleep(long millis) throws InterruptedException {
        Thread.sleep(millis, 0);
    }

    @FastNative
    private static native void sleep(Object lock, long millis, int nanos)
        throws InterruptedException;

發(fā)現(xiàn)官方注釋上面,sleep的時候是沒有 釋放資源鎖的。這就是跟wait最大的區(qū)別.
下面寫對應(yīng)例子驗證:

    private Object waitObj = new Object();
    public void funForWait(int id) {
        synchronized(waitObj) {
            Log.e("@@@", "wait  begin   " + id);
            try {
                waitObj.wait();
            }catch (Exception e) {
                e.printStackTrace();
            }
            Log.e("@@@", "wait  end : " + id);
        }
    }

    public void funForSleep(int id) {
        synchronized(waitObj) {
            Log.e("@@@", "sleep  begin : " + id);
            try {
                Thread.sleep(2000);
            }catch (Exception e) {
                e.printStackTrace();
            }
            Log.e("@@@", "sleep  end : " + id);
        }
    }

        for (int  i = 0; i < 4; i++) {
            final int id = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    funForWait(id);
                }
            }).start();
        }

上面測試wait和sleep分別輸出入下:

wait   
E/@@@: wait  begin   0
E/@@@: wait  begin   1
E/@@@: wait  begin   2
E/@@@: wait  begin   3

sleep:
E/@@@: sleep  begin : 0
E/@@@: sleep  end : 0
E/@@@: sleep  begin : 1
E/@@@: sleep  end : 1
E/@@@: sleep  begin : 3
E/@@@: sleep  end : 3
E/@@@: sleep  begin : 2
E/@@@: sleep  end : 2

從上面的輸出可以看出,當(dāng)調(diào)用wait的時候,其他線程是可以繼續(xù)調(diào)用funForwait方法并且訪問

Log.e("@@@", "wait begin " + id);

而調(diào)用sleep的則不行,從這里可以看出,wait的時候,線程是釋放了對Object的鎖,而sleep卻沒有,所以

Log.e("@@@", "sleep begin : " + id);

這段代碼當(dāng)?shù)谝粋€線程進(jìn)入sleep的時候,其他線程被掛起并且訪問不了這段代碼,原因是因為當(dāng)前線程還是持有Object資源鎖。

如果想要中斷當(dāng)前正在掛起等待的線程,可以調(diào)用

/**
  * <p> If this thread is blocked in an invocation of the {@link
     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
     * class, or of the {@link #join()}, {@link #join(long)}, {@link
     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
     * methods of this class, then its interrupt status will be cleared and it
     * will receive an {@link InterruptedException}.
***
   */
    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                nativeInterrupt();
                b.interrupt(this);
                return;
            }
        }
        nativeInterrupt();
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容