四、线程的调度与控制
通常我们的计算机只有一个CPU,CPU在某一个时刻只能执行一条指令,线程只有得到 CPU
时间片,也就是使用权,才可以执行指令。在单 CPU的机器上线程不是并行运行的,只有
在多个CPU上线程才可以并行运行。 Java虚拟机要负责线程的调度,取得CPU的使用权,
目前有两种调度模型:分时调度模型和抢占式调度模型, Java使用抢占式调度模型。
分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用 CPU的时间片
抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机
选择一个, 优先级高的线程获取的CPU时间片相对多一些 。
1、线程优先级
线程优先级主要分三种: MAX_PRIORITY(最高级 );MIN_PRIORITY(最低级)
NORM_PRIORITY(标准)默认
public class ThreadTest {
public static void main(String[] args) {
Runnable runnable = new Processor();
Thread thread1 = new Thread(runnable, "t1");
thread1.setPriority(Thread.MAX_PRIORITY);
thread1.start();
System.out.println(thread1.getName());
Thread thread2 = new Thread(runnable, "t2");
thread2.setPriority(Thread.MIN_PRIORITY);
thread2.start();
System.out.println(thread2.getName());
}
}
class Processor implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "," + i);
}
}
}
从以上输出结果应该看可以看出,优先级高的线程( t1)会得到的 CPU时间多一些,优先
执行完成。
2、Thread.sleep
态,放弃CPU,腾出cpu时间片,给其他线程用,所以在开发中通常我们会这样做,使其他
的线程能够取得 CPU时间片, 当睡眠时间到达了, 线程会进入可运行状态, 得到CPU时间
片继续执行,如果线程在睡眠状态被中断了,将会抛出IterruptedException
public class ThreadTest {
public static void main(String[] args) {
Processor processor = new Processor();
Thread thread1 = new Thread(processor, "t1");
Thread thread2 = new Thread(processor, "t2");
thread1.start();
thread2.start();
}
}
class Processor implements Runnable {
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println(Thread.currentThread().getName() + "," + i);
if (i % 10 == 0) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
3、t.join(成员方法)
当前线程可以调用另一个线程的 join 方法,调用后当前线程会被阻塞不再执行,直到被调
用的线程执行完毕,当前线程才会执行
public class ThreadTest {
public static void main(String[] args) {
Processor processor = new Processor();
Thread thread = new Thread(processor, "t1");
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("main end");
}
}
class Processor implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "," + i);
}
}
}
4、interrupt(中断 )
如果我们的线程正在睡眠,可以采用interrupt进行中断
public class ThreadTest {
public static void main(String[] args) {
Runnable runnable = new Processor();
Thread thread = new Thread(runnable, "t1");
thread.start();
try {
System.out.println("开始");
Thread.sleep(3000);
System.out.println("结束");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thread.interrupt();
}
}
class Processor implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "," + i);
if (i % 50 == 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
5、如何正确的停止一个线程
通常定义一个标记,来判断标记的状态停止线程的执行
public class ThreadTest {
public static void main(String[] args) {
Processor processor = new Processor();
Thread thread = new Thread(processor, "t1");
thread.start();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
processor8.setFlag(true);
}
}
class Processor implements Runnable {
private boolean flag;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "," + i);
if (flag) {
break;
}
}
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}