java 中 sleep 和 wait 的区别
2个回答
展开全部
首先:sleep是通过线程来调用的。它是Thread身上的方法。而wait是Object身上的方法。
所以调用的时候需要用object来调用。
其次:原理不同。当前线程在同步代码块中,调用sleep之后,当前线程并没有释放锁。意味着
其他线程如果竞争这个锁。就要等待。
而当前线程在同步代码块中调用obj.wait之后。当前线程已经释放锁了。意味着其他对象,如果竞争
这个锁。不需要等待。
说这么多,不如上代码。场景:两个线程同时竞争一个资源。使用同步代码块。
① 竞争同一个obj对象,使用sleep。
public class TestSleep {
public static void main(String[] args) throws Exception{
final Object obj = new Object();
final Thread t1 = new Thread(){
@Override
public void run(){
synchronized (obj) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1");
}
}
};
final Thread t2 = new Thread(){
@Override
public void run(){
synchronized (obj) {
System.out.println("2");
}
}
};
t1.start();
Thread.sleep(100);//确保t1先执行。先抢到obj的控制权。
t2.start();
}
}
分析:创建一个obj。两条线程。Thread.sleep(100);确保让t1先执行到run方法。所以t1会
先抢到obj的资源,给它上锁。需要睡000ms,并不释放obj锁。此时t2已经跑起来,走到run方法同步代码块。
发现obj已经被t1抢到了。所以t2只能等t1释放obj锁。而t1什么时候释放obj锁?t1的同步代码
块执行完释放。什么时候执行完?打印1的时候执行完。t1释放锁之后。t2得到锁。因为这里只有两条
线程竞争obj锁。所以接下来就打印2。
最终结果是先打印1 再打印2。
再看另个一例子:
② 竞争同一个obj对象,使用wait。
public class TestWaint {
public static void main(String[] args) throws Exception{
final Object obj = new Object();
final Thread t1 = new Thread(){
@Override
public void run(){
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1");
}
}
};
final Thread t2 = new Thread(){
@Override
public void run(){
synchronized (obj) {
System.out.println("2");
obj.notify();
}
}
};
t1.start();
Thread.sleep(100);//确保t1先执行。
t2.start();
}
}
分析:创建一个obj。两条线程。Thread.sleep(100);确保让t1先执行到run方法。所以t1会
先抢到obj的资源,给它上锁。然而接下来t1中调用了obj.wait();这个代码,表示t1放弃对obj
的拥有权。也就是释放锁。(释放了之后它需要等待。而不是往下执行,等待什么?等待别人唤醒。
因为wait和notify方法相对。必须要有一个线程调用obj.nofity();时,t1才有可能再次苏醒。否则永远等待。)
t1释放锁,进入等待。意味着t2不用等到t1的同步代码块结束,就可以获取到obj的控制权。
所以t2就给obj上锁了。所以t2先打印 2 。然后调用了obj.nofity();此时t2已经结束。
由于没有其他线程和t1竞争。此时t1苏醒,再次获获得obj的控制权。往下走,t1线程结束。
所以:先打印 2 再打印 1
讲了挺多。我也觉得啰嗦。但是应该通俗易懂吧。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2017-11-09 · 百度知道合伙人官方认证企业
育知同创教育
1【专注:Python+人工智能|Java大数据|HTML5培训】 2【免费提供名师直播课堂、公开课及视频教程】 3【地址:北京市昌平区三旗百汇物美大卖场2层,微信公众号:yuzhitc】
向TA提问
关注
展开全部
Java中的多线程是一种抢占式的机制而不是分时机制。线程主要有以下几种状态:可运行,运行,阻塞,死亡。抢占式机制指的是有多个线程处于可运行状态,但是只有一个线程在运行。
当有多个线程访问共享数据的时候,就需要对线程进行同步。线程中的几个主要方法的比较:
Thread类的方法:sleep(),yield()等
Object的方法:wait()和notify()等
每个对象都有一个机锁来控制同步访问。Synchronized关键字可以和对象的机锁交互,来实现线程的同步。
由于sleep()方法是Thread类的方法,因此它不能改变对象的机锁。所以当在一个Synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放,其他线程仍然无法访问这个对象。而wait()方法则会在线程休眠的同时释放掉机锁,其他线程可以访问该对象。
Yield()方法是停止当前线程,让同等优先权的线程运行。如果没有同等优先权的线程,那么Yield()方法将不会起作用。
一个线程结束的标志是:run()方法结束。
一个机锁被释放的标志是:synchronized块或方法结束。
Wait()方法和notify()方法:当一个线程执行到wait()方法时(线程休眠且释放机锁),它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()前的中断现场。
当有多个线程访问共享数据的时候,就需要对线程进行同步。线程中的几个主要方法的比较:
Thread类的方法:sleep(),yield()等
Object的方法:wait()和notify()等
每个对象都有一个机锁来控制同步访问。Synchronized关键字可以和对象的机锁交互,来实现线程的同步。
由于sleep()方法是Thread类的方法,因此它不能改变对象的机锁。所以当在一个Synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放,其他线程仍然无法访问这个对象。而wait()方法则会在线程休眠的同时释放掉机锁,其他线程可以访问该对象。
Yield()方法是停止当前线程,让同等优先权的线程运行。如果没有同等优先权的线程,那么Yield()方法将不会起作用。
一个线程结束的标志是:run()方法结束。
一个机锁被释放的标志是:synchronized块或方法结束。
Wait()方法和notify()方法:当一个线程执行到wait()方法时(线程休眠且释放机锁),它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()前的中断现场。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询