java.lang.Thread.sleep()方法和java.lang.Object.wait()方法之间的区别

java.lang.Thread.sleep():

sleep()方法为Thread类定义的静态方法,因此需要通过Thread类调用该方法:

Thread.sleep(1000);

Javadoc对该方法的描述如下:

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.

调用sleep()方法将会导致当前正在执行线程休眠特定的时间

在Java字节码层面,获取锁的字节码指令为:monitorenter,释放锁的字节码指令为:monitorexit,所以我个人认为doc里的monitors可以理解为对象锁

也就是说,调用sleep()方法后进入休眠状态的线程并不会释放其持有的对象锁

package com.sean;

public class Test implements Runnable {

	@Override
	public void run(){
		this.s();
	}
	
	public synchronized void s(){
		System.out.println(Thread.currentThread().getName()
				+ " get lock.");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()
				+ " release lock.");
	} 
	
public static void main(String[] args){
		Test st = new Test();
		Thread t1 = new Thread(st, "t1");
		Thread t2 = new Thread(st, "t2");
		t1.start();	
		t2.start();
	}
}

执行结果如下(t2虽然已经启动,但是直到t1释放锁后才能开始执行):

t1 get lock.
t1 release lock.
t2 get lock.
t2 release lock.

 

java.lang.Object.wait():

wait()方法是Object类定义的普通方法,因此任何对象都可调用该方法

this.wait(1000);

Javadoc对wait()方法的描述如下:

Causes the current thread to wait until either another thread invokes the java.lang.Object.notify() method or the java.lang.Object.notifyAll() method for this object, or a specified amount of time has elapsed.

The current thread must own this object's monitor.

This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

  • Some other thread invokes the notify method for this object and thread T happens to bearbitrarily chosen as the thread to be awakened. (参见notify()方法的Javadoc:If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation)
  • Some other thread invokes the notifyAll method for this object.
  • Some other thread interrupts thread T.
  • The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.

The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object; once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.

A thread can also wake up without being notified, interrupted, or timing out, a so-calledspurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:

synchronized (obj) {
	while (<condition does not hold>)
        	obj.wait(timeout);
         	... // Perform action appropriate to condition
}

If the current thread is interrupted by any thread before or while it is waiting, then anInterruptedException is thrown. This exception is not thrown until the lock status of this object has been restored as described above.

Note that the wait method, as it places the current thread into the wait set for this object, unlocks only this object; any other objects on which the current thread may be synchronized remain locked while the thread waits. (这点要特别注意)

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways(简单来说就是获取该对象的锁):

  • By executing a synchronized instance method of that object(调用该对象的同步方法).
  • By executing the body of a synchronized statement that synchronizes on the object(进入该对象的同步代码块).
  • For objects of type Class, by executing a synchronized static method of that class(调用该对象的同步静态方法).

Only one thread at a time can own an object's monitor.

wait()方法、notify()方法和notifyAll()方法都需要先获取到对象上的锁后才能调用,否则会报java.lang.IllegalMonitorStateException

当线程调用对象的wait()方法后,线程将进入等待状态并释放其持有的该对象上的锁(线程仍然持有其它对象的锁)

当对象的notify()方法、notifyAll()方法被调用,或者线程被中断,或者线程等待了wait()方法指定的等待时间(如果为wait(0),则只有对象的notify()方法或notifyAll()方法被调用后线程才会退出等待状态)后,线程将退出等待状态,并和其它线程公平的竞争对象上的锁,一旦线程成功获取到对象锁,线程将从wait()方法调用返回,对象的同步状态和线程的同步状态将和wait()方法调时一样

package com.sean;
public class Test1 implements Runnable {
	private Object lock;
	
	public Test1(Object lock){
		this.lock = lock;
	}

	@Override
	public void run(){
		synchronized(lock){
			System.out.println(Thread.currentThread().getName()
					+ " get lock.");
			try {
				lock.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()
					+ " release lock.");
		}
	}
}
package com.sean;

public class Test2 implements Runnable {
	private Object lock;
	
	public Test2(Object lock){
		this.lock = lock;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(2*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		synchronized(lock){
			System.out.println(Thread.currentThread().getName()
					+ " get lock.");
			lock.notifyAll();
			System.out.println(Thread.currentThread().getName()
					+ " release lock.");
		}
		synchronized(lock){
			System.out.println(Thread.currentThread().getName()
					+ " get lock.");
			System.out.println(Thread.currentThread().getName()
					+ " release lock.");
		}
	}
	
	public static void main(String[] args){
		Object lock = new Object();
		Thread t1 = new Thread(new Test1(lock), "t1");
		Thread t2 = new Thread(new Test2(lock), "t2");
		t1.start();
		t2.start();
	}
}

执行结果如下:

t1 get lock.
t2 get lock.
t2 release lock.
t2 get lock.
t2 release lock.
t1 release lock.

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当一个线程正在等待另一个线程执行一个特定的操作,但是该操作无法立即完成时,线程就会处于WAITING(停车)状态。在这种状态下,线程不会占用CPU时间,直到另一个线程执行了特定的操作并且通知该线程可以继续执行为止。 例如,在线程A中调用了线程B的join()方法,这将导致线程A进入WAITING状态,直到线程B执行完毕并且线程A被唤醒才能继续执行。另一个例子是线程等待某个对象的锁,当该对象被另一个线程持有时,该线程将进入WAITING状态,直到该对象被释放为止。 ### 回答2: java.lang.Thread.State.WAITING(停车)是Java中的一个线程状态。 当一个线程处于WAITING状态时,表示该线程暂时停止执行,等待其他线程的通知或者特定条件的满足。 一个线程在WAITING状态下,可以进入以下几种情况: 1. 使用了Object类的wait()方法。这个方法是在同步代码块中调用的,让正在运行的线程暂时停止执行,并释放对当前对象的锁,直到其他线程调用了notify()或者notifyAll()方法来唤醒该线程。 2. 使用了Thread类的join()方法。当一个线程调用另一个线程的join()方法时,当前线程会进入WAITING状态,直到被调用的线程执行结束。 3. 使用了Lock类中的Condition.await()方法。这个方法会使得当前线程释放锁,并进入WAITING状态,直到其他线程调用了Condition对象的signal()或者signalAll()方法。 4. 使用了LockSupport类的park()方法。这个方法会使得当前线程暂停执行,并等待其他线程调用unpark()方法来唤醒该线程。 在WAITING状态下的线程需要等待其他线程的唤醒或者特定条件的满足,直到满足条件后才能继续执行。一旦满足条件,线程会从WAITING状态转换为可运行的状态(RUNNABLE)并开始执行。 同时需要注意的是,WAITING状态是线程的一种暂时性状态,不会一直保持。一旦条件满足,线程会自动转换回到可运行的状态,继续执行任务。 ### 回答3: java.lang.Thread.State.WAITING(停车)是java.lang.Thread类中的一个线程状态,表示线程正在等待某个特定条件的发生。当线程处于WAITING状态时,它正在等待另一个线程执行特定的操作,以便唤醒它继续执行。 在WAITING状态下,线程会停止执行并等待被唤醒。唤醒线程的条件可以是以下几种情况之一: 1. 线程调用了对象的wait()方法,进入了对象的等待队列,等待其他线程调用相同对象的notify()或notifyAll()方法来唤醒它。 2. 线程调用了Thread.sleep()方法,进入了一个暂停状态,等待指定的时间后自动唤醒。 3. 线程调用了一个等待IO操作的方法,例如read()或accept(),此时线程会等待IO完成后才能继续执行。 在WAITING状态下,线程不会占用CPU资源,而是处于一种被动等待的状态。一旦满足了唤醒条件,线程就会从WAITING状态转变为RUNNABLE状态,并开始竞争CPU资源。 需要注意的是,WAITING状态和BLOCKED状态有所区别WAITING状态表示线程正在主动等待某个特定条件的发生,而BLOCKED状态表示线程被其他线程所阻塞,例如正在等待获取一个锁。 总而言之,java.lang.Thread.State.WAITING(停车)是线程的一种状态,表示线程正在等待某个条件的发生。只有当条件满足时,线程才会被唤醒,继续执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值