A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王丽   /  2011-7-27 06:18  /  5488 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

线程中sleep() 和yield() 的区别是什么?什么情况用哪个方法更好?

评分

参与人数 1技术分 +2 收起 理由
admin + 2 看看马友们的回答!

查看全部评分

7 个回复

倒序浏览
黑马网友  发表于 2011-7-27 06:45:55
沙发
这俩个都是 Thread的方法

sleep(long millis, int nanos)
          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。


yield()
          暂停当前正在执行的线程对象,并执行其他线程。

评分

参与人数 1技术分 +1 收起 理由
admin + 1 答到边了的都有分哦!

查看全部评分

回复 使用道具 举报
yield()调用是安全的
但是没有机制保证会执行,只是一个标志,表示当前线程可以被切换

评分

参与人数 1技术分 +1 收起 理由
admin + 1 答题有分!

查看全部评分

回复 使用道具 举报
sleep()方法,使当前正在执行的线程,放弃CPU,而睡眠指定的时间。
范例1:sleep。[code=java]package org.cxy.demo;
public class Demo extends Thread{
        public Demo(String name){
                super(name);
        }
        public static void main(String[] args) {
                Demo t1 = new Demo("小猫");
                Demo t2 = new Demo("小鸟");
                t1.start();
                t2.start();
        }
        public void run(){
                try {
                        System.out.println(Thread.currentThread().getName()+"说:我要进行秒睡!");
                        Thread.sleep(2000);
                        System.out.println(Thread.currentThread().getName()+"说:睡了2秒醒了!");
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
        }
}[/code]当一个线程睡眠的时候,CPU会转去为其他线程服务去,程序执行的结果:[code=java]小鸟说:我要进行秒睡!
小猫说:我要进行秒睡!
// 注意,此处会等待2秒。然后输出之后的两句。
小猫说:睡了2秒醒了!
小鸟说:睡了2秒醒了![/code]因此,可以使用sleep方法,来完成线程间的切换(调度)。若在run方法中,没有使用Thread.sleep()方法,那么程序的执行结果,可能是这样的:[code=java]小猫说:我要进行秒睡!
小猫说:睡了2秒醒了!
小鸟说:我要进行秒睡!
小鸟说:睡了2秒醒了![/code]此时,这四句话的,被说出的顺序,就不太确定了。除了能保证“小猫说:我要进行秒睡!”将在“小猫说:睡了2秒醒了!”之前被打印出来,“小鸟说:我要进行秒睡!”在“小鸟说:睡了2秒醒了!”之前被打印出来,之外,其他的无法保证。

yield(),即线程让步。
范例2:yield。[code=java]package org.cxy.demo;
public class Demo extends Thread{
        public Demo(String name){
                super(name);
        }
        public static void main(String[] args) {
                Demo t1 = new Demo("小猫");
                Demo t2 = new Demo("小鸟");
                t1.start();
                t2.start();
        }
        public void run(){
                System.out.println(Thread.currentThread().getName()+"说:我要进行秒睡!");
                Thread.currentThread().yield();
                System.out.println(Thread.currentThread().getName()+"说:睡了2秒醒了!");
        }
}[/code]•  使用Thread类的静态方法yield() 进行让步操作。
  •  yield()方法使当前线程放弃本次抢到的CPU,回到就绪状态。从而使其他线程可以运行。但此方法同样没有任何保障。让步的线程可能再次被选中。
  •  此方法不能保证做太多的事,尽管通常它会使当前线程回到就绪状态,并使具有相同优先级的线程能够有机会运行。
  •  强烈提示:如果你的一些高优先级的线程很少发生阻塞,那么你的低优先级的线程可能永远都运行不了。


    因此,他们二人都可以使线程放弃当前的cpu。 sleep可以让线程在放弃cpu后,有一段时间内不能参与cpu的竞争。而yield方法,仅仅是进行简单的线程让步,但是让步的线程可能再次被选中。
    另外,提示一下,当在同步方法中,使某个线程调用了sleep方法,则该线程不会释放锁。
[ 本帖最后由 崔虎 于 2011-07-27  08:37 编辑 ]

评分

参与人数 1技术分 +3 收起 理由
admin + 3 加分必须的!

查看全部评分

回复 使用道具 举报
黑马网友  发表于 2011-7-27 09:00:53
报纸
sleep ()方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的,yield ()方法使当前线程让出CPU占有权,但让出的时间是不可设定的。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
黑马网友  发表于 2011-7-27 09:08:55
地板
[size=3]sleep()方法是自行休眠,把cpu让给优先级别比其低的线程,当到了限定的时间后 该线程进入运行状态。[/size]
[size=3]
[/size]
[size=3]yield()是使具有与当前线程相同优先级别相同的线程有运行的机会。如果有其他的线程与当前线程有相同的优先级并且是可运行的。该方法将被调入到可运行线程池,并允许其他线程运行。如果没有相同优先级的线程是Runnable状态。那么该方法什么也不做,即该线程将继续运行。[/size]

评分

参与人数 1技术分 +2 收起 理由
admin + 2 新手报到!

查看全部评分

回复 使用道具 举报
黑马网友  发表于 2011-7-27 10:18:35
7#
:lol 虎哥回答的入情入理
[color=Red]sleep方法和yield方法的区别[/color]
1、sleep方法暂停当前的线程后,会给其他的线程执行的机会,不会理会其他线程的优先级,但是yield方法只会给优先级相同,或者优先级更高的线程执行的机会
2、sleep方法会将线程转入阻塞状态,知道经过阻塞时间才会转入就绪状态,而yield方法不会讲线程转入阻塞状态,它只是强制当前线程进入就绪状态,因此完全有可能某个线程调用yield 方法暂停之后,这个线程又立即获得处理器资源执行。
3、sleep方法声明抛出了interruptedException异常,所以调用sleep方法时候要么捕捉这个异常,要么显示声明抛出这个异常,而yield方法则没有声明抛出任何异常
4、sleep方法比yield方法有更好的可移植性,通常不需要依靠yield来控制并发线程的执行

如下两个程序简单说明两个方法的用法:
[color=Red]线程睡眠:sleep[/color][code=java]package cn.itcast.heima
import java.util.*;

public class TestSleep
{
    public static void main(String[] args) throws Exception
    {
                for (int i = 0; i < 10 ; i++ )
                {
                        System.out.println("当前时间: " + new Date());
                        //调用sleep方法让当前线程暂停1s。
                        Thread.sleep(1000);
                }
    }
}[/code][color=Blue]这个程序可看出程序结果两条字符串之间时间间隔为1秒[/color]
[color=Red]
线程让步:yield[/color][code=java]package cn.itcast.heima
public class TestYield extends Thread
{
        public TestYield()
        {
        }
        public TestYield(String name)
        {
                super(name);
        }
        //定义run方法作为线程执行体
        public void run()
        {
                for (int i = 0; i < 50 ; i++ )
                {
                        System.out.println(getName() + "  " + i);
                        //当i等于20时,使用yield方法让当前线程让步
                        if (i == 20)
                        {
                                Thread.yield();
                        }
                }
        }
    public static void main(String[] args) throws Exception
    {
                //启动两条并发线程
                TestYield ty1 = new TestYield("高级");
                //将ty1线程设置成最高优先级
                ty1.setPriority(Thread.MAX_PRIORITY);
                ty1.start();
                TestYield ty2 = new TestYield("低级");
                //将ty1线程设置成最低优先级
                ty2.setPriority(Thread.MIN_PRIORITY);
                ty2.start();       
    }
}[/code]上面程序run方法调用yield方法让线程暂停,让系统线程调度器重新调度,当后面[code=java]ty1.setPriority(Thread.MAX_PRIORITY);
ty2.setPriority(Thread.MIN_PRIORITY);[/code]、
[color=Blue]注释的时候,--也就是两条线程的优先级一样,所以其中一条线程使用yield方法站台,另外一条线程就会执行,
如果我们不注释上面两个代码,那么可以看到当一条线程调用yield方法之后又马上获得了执行的机会[/color]

评分

参与人数 1技术分 +3 收起 理由
admin + 3 你很用心!

查看全部评分

回复 使用道具 举报
黑马网友  发表于 2011-7-27 10:19:50
8#
1) sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

2) sleep()可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会;yield()只能使同优先级的线程有执行的机会。

class TestThreadMethod extends Thread{  
public static int shareVar = 0;  
public TestThreadMethod(String name){  
super(name);  
}  
public void run(){  
for(int i=0; i<4; i++){  
System.out.print(Thread.currentThread().getName());  
System.out.println(" : " + i);  
//Thread.yield(); (1)  
/* (2) */  
try{  
Thread.sleep(3000);  
}  
catch(InterruptedException e){  
System.out.println("Interrupted");  
}}}  
}  
public class TestThread{  
public static void main(String[] args){  
TestThreadMethod t1 = new TestThreadMethod("t1");  
TestThreadMethod t2 = new TestThreadMethod("t2");  
t1.setPriority(Thread.MAX_PRIORITY);  
t2.setPriority(Thread.MIN_PRIORITY);  
t1.start();  
t2.start();  
}  
}
运行结果为:

t1 : 0  
t1 : 1  
t2 : 0  
t1 : 2  
t2 : 1  
t1 : 3  
t2 : 2  
t2 : 3
由结果可见,通过sleep()可使优先级较低的线程有执行的机会。注释掉代码(2),并去掉代码(1)的注释,结果为:

t1 : 0  
t1 : 1  
t1 : 2  
t1 : 3  
t2 : 0  
t2 : 1  
t2 : 2  
t2 : 3
可见,调用yield(),不同优先级的线程永远不会得到执行机会。

评分

参与人数 1技术分 +2 收起 理由
admin + 2 不错!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马