线程的调度
在单CPU的计算机中,一个时刻只有一个线程运行。所谓多线程并行 工作,即在微观上,各个线程在极小 的时间段内,轮流获得CPU资源的使用权。在宏观 上,则表现为多个线程同时执行。即使在多CPU的计算机中,线程数量超过CPU数量时,处于运行状态的多个线程,依然需要排队等待CPU资源。
在Java中,可以通过以下4种方法,来为多个线程分配CPU的使用权:
- 设置优先级(Priority)
- 休眠(sleep)
- 强制运行(join)
- 礼让(yield)
线程的优先级
线程的优先级使用1~10表示,10最高,默认值是5。
class ThreadDemoForPriority implements Runnable {
@Override
public void run() { //实现run方法
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName()
+ "正在运行:" + i);
}
}
public static void main(String[] args) {
//创建两个线程,通过构造方法指定线程名
Thread t1 = new Thread(new ThreadDemoForPriority(), "线程1");
Thread t2 = new Thread(new ThreadDemoForPriority(), "线程2");
//设置线程的优先级
t1.setPriority(Thread.MAX_PRIORITY); //最大优先级
t2.setPriority(Thread.MIN_PRIORITY); //最小优先级
//显示线程的优先级
System.out.println("线程1的优先级: " + t1.getPriority());
System.out.println("线程2的优先级: " + t2.getPriority());
//t1.setPriority(6); //可以取消注释,用于测试
//t2.setPriority(5);
System.out.println("****************");
t1.start();
t2.start();
}
}
一般情况下,优先级高的线程获得CPU的概率较大。但这个结果不是绝对的,线程优先级调度是一个复杂的过程,具体可以参考代码中的注释部分。
线程的休眠
Thread.sleep()方法会让当前线程休眠(停止执行),线程由运行状态进入阻塞状态,休眠时间过后线程会再次进入运行状态。调用sleep()方法需处理InterruptedException异常。
class Wait {
static void bySec(long s) {
for (int i = 0; i < s; i++) {
System.out.println(i + 1 + "秒");
try {
Thread.sleep(1000); //1000毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ThreadDemoForSleep {
public static void main(String[] args) {
System.out.println("主线程执行step1");
System.out.println("主线程等待中:");
Wait.bySec(5); //让主线程等待5秒再执行
System.out.println("等待结束");
System.out.println("主线程执行step2");
}
}
线程的强制运行
join()方法使当前的线程暂停执行,等待调用该方法的线程结束后再继续执行本线程。调用join()方法同样需要处理InterruptedException异常。
public class ThrJoin implements Runnable {
public void run() {
for (int i = 1; i <= 10; i++) {
try {
Thread.sleep(100); //增加线程交替执行的概率
} catch (InterruptedException e) {
e.printStackTrace();
}
//输出当前线程的信息
System.out.println(Thread.currentThread().getName()+"运行:"+i);
}
}
}
public class ThreadDemoForJoin {
public static void main(String[] args) {
System.out.println("******线程强制执行*****");
//创建子线程并启动
Thread temp = new Thread(new ThrJoin());
temp.start();
for (int i = 1; i <= 20; i++) {
if (i == 5) {
//当主线程准备执行第5次时
try {
//阻塞主线程,子线程强制执行
temp.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100); //增加线程交替执行的概率
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行:"+i);
}
}
}
*此程序运行几次会有不同的结果
线程的礼让
yield()方法可以暂停当前线程的执行,允许其他具有相同优先级的线程获得运行机会。该线程扔处于就绪状态,不转为阻塞状态。
public class ThrYield implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "正在运行:" + i);
if (i == 3) {
System.out.print("线程礼让:");
Thread.yield();
}
}
}
}
public class ThreadDemoForYield {
public static void main(String[] args) {
ThrYield my=new ThrYield();
Thread t1 = new Thread(my, "线程A");
Thread t2 = new Thread(my, "线程B");
t1.start();
t2.start();
}
}
*此程序运行几次会有不同的结果
使用yield()的线程礼让只是提供一种可能,但不能保证一定会实现礼让。因为礼让的线程处于就绪状态,还有可能被线程调度程序再次选中。
小结:
本章介绍了线程调度的4中方法,下一章讨论使用多线程会遇到的问题。