前言:
前几天复习了一下多线程,发现有许多网上讲的都很抽象,所以,自己把网上的一些案例总结了一下!

一、Thread.yield( )方法:

使用yield()的目的是 让具有相同优先级或者更高优秀级的线程之间能够适当的轮换执行当一个线程使用了yield( )方法之后,它就会把自己CPU执行的时间让掉让自己或者其它的线程运行

使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行

举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,有可能是其他人先上车了,也有可能是Yield先上车了。

线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的

打个比方:现在有很多人在排队上厕所,好不容易轮到这个人上厕所了,突然这个人说:“我要和大家来个竞赛,看谁先抢到厕所!”,然后所有的人在同一起跑线冲向厕所,有可能是别人抢到了,也有可能他自己有抢到了。我们还知道线程有个优先级的问题,那么手里有优先权的这些人就一定能抢到厕所的位置吗? 不一定的,他们只是概率上大些,也有可能没特权的抢到了。

二、实例

例子1:

package com.yield;
 
public class YieldTest extends Thread {
 
	public YieldTest(String name) {
		super(name);
	}
 
	@Override
	public void run() {
		for (int i = 1; i <= 50; i++) {
			System.out.println("" + this.getName() + "-----" + i);
			// 当i为30时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
			if (i == 30) {
				this.yield();
			}
		}
	}
 
	public static void main(String[] args) {
		YieldTest yt1 = new YieldTest("张三");
		YieldTest yt2 = new YieldTest("李四");
		yt1.start();
		yt2.start();
	}
}

运行结果:
注意:测试环境为单核

  • 第一种情况:李四(线程)当执行到30时会CPU时间让掉,这时张三(线程)抢到CPU时间并执行。
  • 第二种情况:李四(线程)当执行到30时会CPU时间让掉,这时李四(线程)抢到CPU时间并执行。

例子2:

public class yeld {
 
	public static void main(String[] args) {
		ThreadDemo demo = new ThreadDemo();
		Thread thread = new Thread(demo, "花花");
		Thread thread1 = new Thread(demo, "草草");
		thread.start();
		thread1.start();
	}
}
 
class ThreadDemo implements Runnable {
 
	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			if (i == 3) {
				System.out.println("当前的线程是     " + Thread.currentThread().getName());
				Thread.currentThread().yield();
			}
			System.out.println("执行的是    " + Thread.currentThread().getName());
		}
 
	}
 
}

运行结果

执行的是    草草
    执行的是    草草
    执行的是    草草
    当前的线程是     草草 //并没有礼让
    执行的是    草草
    执行的是    草草
    执行的是    花花
    执行的是    花花
    执行的是    花花
    当前的线程是     草草 //礼让啦
    执行的是    花花
    执行的是    花花

例子3:

线程的yield()只会将运行权让给相同优先级或更高的优先级执行。这样就很容易使读者以为,如果有两个线程a和b,a的优先级大于b的优先级,即使a调用了yeild()方法,由于b的优先权低于a,那么线程需要等a运行完之后b才有机会运行,是这样的?

public class YieldTest extends Thread {

    private String name;

    public YieldTest(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            if (name.equals("李四")) {
                yield();
            }
            System.out.println("" + name + "-----" + i);
        }
    }

    public static void main(String[] args) {
        YieldTest yt1 = new YieldTest("张三");
        YieldTest yt2 = new YieldTest("李四");
        yt1.setPriority(MIN_PRIORITY);
        yt2.setPriority(MAX_PRIORITY);
        yt1.start();
        yt2.start();
    }
}

“李四"这个线程优先级高于“张三”这个线程,在“李四”线程里面调用了yield()方法,按道理是“李四”这个线程先执行完,“张三”这个线程才开始执行。执行结果如下

张三-----1
李四-----1
李四-----2
李四-----3
李四-----4
李四-----5
张三-----2
李四-----6
张三-----3
李四-----7
张三-----4
李四-----8
张三-----5
李四-----9
张三-----6
李四-----10
张三-----7
张三-----8
张三-----9
张三-----10

从结果可以看出,“张三”线程并不是等“李四”线程执行完之后才开始执行。

其实,首先对于线程的运行,它有一个时间片的概念,线程优先级低的在拿到时间片时也是可以执行的,只不过优先级高的线程会尽可能早的执行罢了,不是说优先级高的一定会先执行。对于yield()方法,可以理解为当前线程是让出了执行权,但是还是要看时间片分到了谁。就算当前线程现在让出了执行权,可能马上它又得到执行权接着执行。

所以千万不要以为调用了yield()方法,低优先级的线程就无法执行,执行线程的开始执行还是要看谁先拿到了执行权