多线程(二)线程的调度

线程的调度

在单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中方法,下一章讨论使用多线程会遇到的问题。

你可能感兴趣的:(Java)