线程的调度(线程休眠,线程让步,线程插队)

程序中的多个线程是并发执行的,某个线程若想被执行必须要得到CPU的使用权,Java虚拟机会按照特定的机制为程序中的每个线程分配CPU的使用权,这种机制被称作线程的调度。

两种线程调度模式:

分时调度模式:让所有的线程轮流获得CPU的使用权,并且平均分配每个线程占用的CPU的时间片。

抢占式调度模式:让可运行池中优先级高的线程优先占用CPU,而对于优先级相同的线程,随机选择一个线程使其占用CPU,当它失去了CPU的使用权后,再随机选择其他线程使其占用CPU。

Java虚拟机默认采用抢占式调度模型。


一、线程的优先级

线程的优先级用1~10之间的整数来表示,数字越大优先级越高。Thread类提供三个静态常量表示线程的优先级:

MAX_PRIORITY :相当于10

MIN_PRIORITY:相当于1

NORM_PRIORITY:相当于5

通常用setPriority(int 优先级)对线程进行设置,但优先级调整的是几率,而不是将优先级低的进程挂起。setPriority 告诉JVM这个线程的优先级,但JVM是否按你请求 (请求,不是要求)办不确定,就是结果不确定难过(最主要原因是这些优先级需要操作系统的支持,不同的操作系统对优先级的支持是不一样的)


二、线程休眠

运用sleep()函数,使正在执行的线程暂停一段时间,将CPU让给别的线程,即让线程进入休眠等待状态。

注意:①sleep()释放资源不释放锁

        ②sleep(long millis)方法生命抛出InterruptedException异常,因此在调用该方法时应该捕获异常,或声明抛出该异常。

//定义SleepThread类实现Runnable接口
class SleepThread implements Runnable {
	public void run() {
		for (int i = 1; i <= 10; i++) {
			System.out.println("线程一正在输出:" + i);

		}
	}
}

public class Example2 {
	public static void main(String[] args) throws Exception {
         // 创建一个线程
		new Thread(new SleepThread()).start();
		for (int i = 1; i <= 10; i++) {
			if (i == 5) {
				System.out.println("主线程暂时休眠500毫秒,接下来是线程一输出");
				Thread.sleep(2000);  // 当前线程休眠2秒
			}
			System.out.println("主线程正在输出:" + i);
		}
	}
}
结果:

线程休眠只是让该线程停一段时间,一段时间之后就可以接着进行,不需要别的线程进行完,例子中因为线程一总执行时间较短,在主线程休眠的时间内就运行完了。


三、线程让步

通过yield()方法,将当前进程停下,换成就绪状态,让系统的调度器重新调度一次。

与sleep()方法相似,但yield()方法不会阻塞该线程,之后该线程与其他线程是相对公平的。调度谁看系统,有可能还是调度它自己。

class YieldThread extends Thread {
    // 定义一个有参的构造方法
	public YieldThread(String name) { 
		super(name); // 调用父类的构造方法
	}
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + "---" + i);
			if (i == 3) {
				System.out.print("线程让步:\n");
				Thread.yield(); // 线程运行到此,作出让步
			}
		}
	}
}
public class Example2 {
	public static void main(String[] args) {
        // 创建两个线程
		Thread t1 = new YieldThread("线程A");
		Thread t2 = new YieldThread("线程B");
        // 开启两个线程
		t1.start();
		t2.start();
	}
}
结果:

通过结果可以看到线程让步之后,有可能系统调度的是别的线程,有可能还是自己。


四、线程插队

就像它的名字,插队,通过join()方法,阻塞当前线程,先完成被join()方法加入的插入的这个线程,之后再完成其他线程。

class EmergencyThread implements Runnable {
	public void run() {
		for (int i = 1; i < 7; i++) {
			System.out.println(Thread.currentThread().getName()+"输出:"+i);
		}
	}
}

public class Example2{
	public static void main(String[] args) throws Exception {
		// 创建线程
		Thread t = new Thread(new EmergencyThread(),"线程一");
		t.start(); // 开启线程
		for (int i = 1; i < 7; i++) {
			System.out.println(Thread.currentThread().getName()+"输出:"+i);
			if (i == 2) {
				//System.out.println("线程1插队");
				t.join(); // 调用join()方法
			}
		}
	}
}
结果:

从结果可以看到,当main线程输出2以后,线程一就开始执行,直到线程一执行完毕,main线程才继续执行。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值