java中多线程(1)之sleep与wait的区别

时间:2022-12-15 15:34:11

sleep是Thread中的函数,JDK中对应的源码如下:

public static void sleep(long millis) throws InterruptedException {
Thread.sleep(millis, 0);
}

public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("millis < 0: " + millis);
}
if (nanos < 0) {
throw new IllegalArgumentException("nanos < 0: " + nanos);
}
if (nanos > 999999) {
throw new IllegalArgumentException("nanos > 999999: " + nanos);
}

// The JLS 3rd edition, section 17.9 says: "...sleep for zero
// time...need not have observable effects."
if (millis == 0 && nanos == 0) {
// ...but we still have to handle being interrupted.
if (Thread.interrupted()) {
throw new InterruptedException();
}
return;
}

long start = System.nanoTime();
long duration = (millis * NANOS_PER_MILLI) + nanos;

Object lock = currentThread().lock;

// Wait may return early, so loop until sleep duration passes.
synchronized (lock) {
while (true) {
sleep(lock, millis, nanos);

long now = System.nanoTime();
long elapsed = now - start;

if (elapsed >= duration) {
break;
}

duration -= elapsed;
start = now;
millis = duration / NANOS_PER_MILLI;
nanos = (int) (duration % NANOS_PER_MILLI);
}
}
}

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

tips:long now = System.nanoTime();它是一个更精确的时间表达,us微秒级别的,常用于精确计时器的使用,但是它的值不是固定的,可以代表过去的某一时刻(正值),也可以代表未来的某一时刻(负值),可以用来倒计时时间的统计.


1.sleep 方法需要捕获底层抛出的InterruptedException异常,sleep方法在倒计时区间内会让出cpu资源给其他线程,等倒计时结束后自动恢复运行状态.

class Thread1 implements Runnable {

@Override
public void run() {
Log.e(TAG, "enter thread1.......");
Log.e(TAG, "thread1 is waiting...");
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
Log.e(TAG, "thread1 is going on ....");
Log.e(TAG, "thread1 is over.....");
}
}

class Thread2 implements Runnable {


@Override
public void run() {
Log.e(TAG, "enter thread2....");
Log.e(TAG, "thread2 is sleep....");
Log.e(TAG, "thread2 is going on....");
Log.e(TAG, "thread2 is over....");
}
}

public void testSleep() {
new Thread(new Thread1()).start();
new Thread(new Thread2()).start();
}

如下的输出验证了上面1中的结论:
java中多线程(1)之sleep与wait的区别

2.在调用sleep()方法的过程中,线程不会释放对象锁.

class Thread1 implements Runnable {

@Override
public void run() {

synchronized (object) {
Log.e(TAG, "enter thread1.......");
Log.e(TAG, "thread1 is waiting...");
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
Log.e(TAG, "thread1 is going on ....");
Log.e(TAG, "thread1 is over.....");
}
}
}

class Thread2 implements Runnable {


@Override
public void run() {
synchronized (object) {
Log.e(TAG, "enter thread2....");
Log.e(TAG, "thread2 is sleep....");
Log.e(TAG, "thread2 is going on....");
Log.e(TAG, "thread2 is over....");
}
}
}

public void testSleep() {
new Thread(new Thread1()).start();
new Thread(new Thread2()).start();
}

输出验证了2中的结论:

java中多线程(1)之sleep与wait的区别


3.wait()方法属于Object对象的方法,当调用wait()方法的时候线程会放弃对象锁,直到等到别的线程调用notify()/notifyAll()方法时本线程才会放入对象锁定池等待执行,否则不会执行下去。

    Object object = new Object();

class Thread1 implements Runnable {

@Override
public void run() {

synchronized (object) {

Log.e(TAG, "enter thread1.......");
Log.e(TAG, "thread1 is waiting...");
try {
object.wait(); //调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池
} catch (Exception e) {
e.printStackTrace();
}
Log.e(TAG, "thread1 is going on ....");
Log.e(TAG, "thread1 is over.....");
}
}
}

class Thread2 implements Runnable {


@Override
public void run() {
synchronized (object) {

Log.e(TAG, "enter thread2....");
Log.e(TAG, "thread2 is sleep....");
//只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
object.notify();
Log.e(TAG, "thread2 is going on....");
Log.e(TAG, "thread2 is over....");
}
}
}

public void testSleep() {
new Thread(new Thread1()).start();
new Thread(new Thread2()).start();
}

输出验证了3中的结论:

java中多线程(1)之sleep与wait的区别