线程的调度
- 线程的调度分为分时调度和抢占式调度:
- 分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间;
- 抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java 使用的为抢占式调度;
1. 线程栈
- 线程栈:某时刻内内存中线程调度的栈信息,当前调用的方法总是位于栈顶,线程栈的内容是随程序的运行动态变化的,所以线程栈必须选择一个运行的时刻(即代码运行到什么地方);
- 线程(调用)栈的变化过程:
2. 线程的优先级
- Java 线程有10个优先级,用数字1~10表示,线程默认的优先级是5级;
- 可以通过
setPriority(int)
方法设置优先级,通过 getPriority()
方法获知一个线程的优先级;
- 有3个常数用于表示线程的优先级:
Thread.MIN_PRIORITY
Thread.MAX_PRIORITY
Thread.NORM_PRIORITY
,对应优先级分别为 1/10/5;
3. 线程休眠
sleep(long millis)
方法用于线程的休眠;
public class Test extends Thread {
public void run() {
loop();
}
public void loop() {
String name = Thread.currentThread().getName();
System.out.println(name + " ---->> 刚进入loop()方法");
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException x) {
}
System.out.println("name=" + name);
}
System.out.println(name + " ---->> 离开loop()方法");
}
public static void main(String[] args) {
Test t = new Test();
t.start();
try {
Thread.sleep(700);
} catch (InterruptedException x) {
}
t.loop();
}
}
4. 线程让步
- 线程让步:指暂停当前正在执行的线程对象,转而执行其他线程;
- 如果当前运行的线程优先级大于或等于线程池中其他线程的优先级,当前线程能获得更多的执行时间;如果当前运行的线程想让和它相同优先级的其他线程获得运行机会,使用让步方法 yield() 即可;
- yield() 方法只是让当前线程从运行状态转到可运行状态;
public class Test {
public static void main(String[] args) {
Thread t1 = new MyThread1();
Thread t2 = new Thread(new MyRunnable1());
t2.start();
t1.start();
}
}
class MyThread1 extends Thread {
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println("线程1 第" + i + "次执行!");
}
}
}
class MyRunnable1 implements Runnable {
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println("线程2 第" + i + "次执行!");
Thread.yield();
}
for (int i = 1; i <= 10000; i++) ;
}
}
5. 线程联合
- join() 方法让一个线程 A 与另一个线程 B 联合,即 A 加到 B 的尾部,自 A 执行完毕前不能执行 B,A 执行完毕,B 才能重新转为可运行状态;
public class Test {
public static void main(String args[]) throws Exception {
Thread sub = new Sub();
sub.setName("子线程");
System.out.println("主线程main 开始执行。");
sub.start();
System.out.println("主线程main 等待线程sub 执行……");
sub.join();
System.out.println("主线程main 结束执行。");
}
}
class Sub extends Thread {
public void run() {
System.out.println(this.getName() + "开始执行。");
System.out.println(this.getName() + "正在执行……");
try {
sleep(3000);
} catch (InterruptedException e) {
System.out.println("interrupted!");
}
System.out.println(this.getName() + "结束执行。");
}
}