EP37-Yield、Sleep

Thread.yield()

让步就是投降,让出CPU资源给其他线程。其他线程自然会抢占->开始执行。
比如让线程的run方法里执行打印动作,在被interrupt之前,每打印5次就yield():

//run()方法里执行的内容
    System.out.println(getName() + "执行了" + ++i + "次");  
    if(i % 5 == 0) {// 被5整除时让步  
        Thread.yield();  
    } 

然后创建两个线程分别开始执行上面的run方法,执行100毫秒。

//t1,t2两个线程分别执行run(),执行100毫秒后中断。
    t1.start();  
    t2.start();  
    Thread.sleep(100);    
    t1.interrupt();  
    t2.interrupt();

结果会发现,t1,t2交替着执行了。

t1执行了1次
t1执行了2次
t1执行了3次
t1执行了4次
t1执行了5次
t2执行了1次
t2执行了2次
t2执行了3次
t2执行了4次
t2执行了5次
t1执行了6次
t1执行了7次
...

这就是线程让步(Yield)了。
这个看起来跟sleep是有点像的,sleep也是让出CPU资源,本线程不执行,其他线程抢占。但sleep到了期限就会醒过来的。yield只能等下次别人再yield才会醒过来。

Thread.sleep()

sleep需要注意一点,就是sleep过程中持有锁。

锁是怎么获得的?每个对象都有一个锁,线程访问synchronized方法/代码块的时候会获得锁。有了锁,别的线程再来访问就只能阻塞住,等待前人执行完了synchronized之后释放锁。

也就是说,如果一个进程是synchronized方法中sleep,即便它在睡觉中,别的线程依旧不能执行这个synchronized方法的。但可以执行这个类的其他方法。这就是互斥

Thread.sleep和Object.lock

sleep()睡眠时,占有对象锁;
而wait()睡眠时,释放对象锁。
为什么呢?可以考虑,sleep是Thread的static类,不能改变Object类的锁。所以不能释放锁。

wait睡眠的时候,wait所在的对象会进入于它相关的线程池,其他线程可以访问这个对象;等wait的时间结束了,或者被interrupt了,或者notify了,再从线程池里唤醒它,同时重新获取到对象的锁。

举个例子,

        int number = 10;
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest);
        thread.start();
        threadTest.secondMethod();

首先看看上面这段话的执行顺序,帅哥说,顺序是:
thread.start();-->threadTest.secondMethod();--> thread里的run方法
笑哥说:
thread.start();
然后threadTest.secondMethod();和 thread里的run方法的话,这两个看CPU资源谁抢到了。
按照网上的说法是,先执行第主线程中的方法,也就是先执行secondMethod();
secondMethod中执行sleep或者wait:

    public void secondMethod() throws Exception {
        synchronized (this) {
            Thread.sleep(2000);
            //this.wait(2000);
            number *= 200;
        }
    }

run()方法里执行:

    @Override
    public void run() {
        try {
            synchronized (this) {
            number += 100;
            System.out.println(number);
        }        
      } catch (Exception e) {
            e.printStackTrace();
        }
    }

sleep和wait的执行区别是,sleep输出2100,wait输出110。这是因为,sleep过程中要等sleep完了,执行了number *= 200;然后才继续执行number += 100;。wait就不会一直拿着锁,所以thread线程先去执行number += 100;了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,482评论 1 15
  • 该文章转自:http://blog.csdn.net/evankaka/article/details/44153...
    加来依蓝阅读 7,378评论 3 87
  • 写在前面的话: 这篇博客是我从这里“转载”的,为什么转载两个字加“”呢?因为这绝不是简单的复制粘贴,我花了五六个小...
    SmartSean阅读 4,780评论 12 45
  • 我们每个人都在演戏,在我们开口说话之前,已经设定好了自己的角色,情节的发展,故事的结尾。很多时候,说这不是...
    小凯兔你阅读 260评论 0 0
  • 大家好,一年一度的中元节昨天又过了,不知道大家小区里踩到多少个圈圈~在这里,小编想说的是: ** 中元普渡 唯...
    战国修罗魂阅读 404评论 0 0