栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多线程学习系列三之线程调度

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多线程学习系列三之线程调度

线程调度 目录
  • 线程调度
    • @[TOC](目录)
  • 前言
  • 一、 两种调度模型
    • 1.1 分时调度模型
    • 1.2 抢占调度(JAVA虚拟机采用的调度模式)
    • 1.3 、线程放弃CPU的原因
  • 二 、Java明确让一个线程给另外一个线程运行机会采用的方法
    • 2.1 调整各个线程的优先级
    • 2.2、线程睡眠: Thread.sleep()方法
    • 2.3、线程让步:Thread.yield()方法
    • 2.4、sleep()和yield()区别
    • 2.5、等待其他线程结束:join()
      • 2.5.1、 join()方法的两种重载形式
前言

  计算机通常只有一个CPU。所谓多线程的并发运行,其实是指宏观上看各个线程轮流获得CPU的使用权。Java虚拟机就是负责线程的调度

一、 两种调度模型 1.1 分时调度模型

  指让所有线程轮流获得CPU的使用权,并且平均分配每个线程占用CPU的时间。

1.2 抢占调度(JAVA虚拟机采用的调度模式)

  指优先让可以运行池中优先级高的线程占用CPU,如果可运行线程池中的优先级相同,那么就随机地选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。

1.3 、线程放弃CPU的原因
  1. Java虚拟机让当前线程暂时放弃CPU ,转到就绪状态,使其他线程获得运行机会。
  2. 当前线程因为某些原因进入阻塞状态
  3. 线程运行结束

Tips

1.线程的调度不是跨平台的,它不仅仅取决于Java寻虚拟机,还依赖于操作系统。
2.Java线程的调度不是分时的,同时启动多个线程后不能保证各个线程轮流获得均等的CPU时间片

二 、Java明确让一个线程给另外一个线程运行机会采用的方法
  1. 调整各个线程的优先级
  2. 让处于运行的线程调用Thread.sleep()方法
  3. 让处于运行状态的线程调用Thread.yueld()方法
  4. 让处于运行状态的线程调用另一个线程的join()方法
2.1 调整各个线程的优先级

  所有处于就绪状态的线程根据优先级存放在可运行池中,优先级低的线程获得较少的运行机会。
  Thread类的**setPriority(int i)和 getPriority()**方法分别来设置优先级和读取优先级。取值范围1~10,Thread常用三个静态变量(建议调整线程优先级时适用默认值)

  1. MAX_PRIORITY: 取值为10,表示最高优先级
  2. MIN_PRIORITY:取值为1,表示最低优先级
  3. NORM_PRIORITY:取值为5,表示默认优先级

注意:

  1. 每个线程都有默认的优先级,主线程的默认优先级为Thread.NORM_PRIORITY。如果线程A创建了线程B,那么B将和A具有同样的优先级。
  2. 尽管java提供了10个优先级,但是它与多数操作系统都不能很好的进行线程优先级的映射。比如Window有7个优先级,并不是固定的。而Solaris操作系统有2^31个优先级。如果希望程序能够移植到各个操作系统中,因该确保在设置线程的优先级时,只使用MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY这三个默认优先级。
2.2、线程睡眠: Thread.sleep()方法

  当一个线程执行了sleep()方法,就会放弃CPU,转到阻塞状态。sleep(Long millis)参数设定睡眠时间,单位:毫秒。当线程睡眠结束,首先转到就绪状态

public class Sleeper extends Thread {
    @Override
    public void run() {
        try {
            sleep(60000);
            System.out.println("sleep over");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }

    public static void main(String[] args) throws InterruptedException {
        Sleeper sleeper = new Sleeper();
        sleeper.start();
        Thread.sleep(10);
        sleeper.interrupt();// 终端睡眠
    }
}
2.3、线程让步:Thread.yield()方法

  当前线程执行yield()静态方法时,如果此时具有相同优先级的其他线程处于就绪状态,yield()方法将当前运行的线程放到可运行池中并使另一个线程运行。如果没有相同优先级的可运行进程,yield()方法什么都不做。

2.4、sleep()和yield()区别
  • sleep()方法会给其他线程运行的机会,不考虑其他线程的优先级,因此会给较低优先级线程一个运行的机会;yield()方法只会给相同优先级或者更高优先级的线程一个运行机会。
  • 当线程执行了sleep(Long millis)方法后,将转到阻塞状态,参数millis指定睡眠时间,当线程执行额yield()方法以后,将转到就绪状态。
  • sleep()方法生命抛出InterruptddException异常,yield()方法不抛出异常
  • sleep()方法比yield()方法具有更好的可移植性。不能依靠yield()方法来提高程序的并发性能。实际开发中几乎不适用yield()方法提高并发性能.
2.5、等待其他线程结束:join()

  当前运行的线程可以调用另一个线程的join()方法。当前运行的线程转到阻塞状态,直至另一个线程运行结束,他才回复运行

2.5.1、 join()方法的两种重载形式
public void join()
public void join(Long timeOut)

timeout参数设定当前线程被阻塞的时间,单位:毫秒

machine.join(10)

当主线程被阻塞的时间超过10毫秒,或者machine线程运行结束时,主线程就恢复运行

public class Machine extends Thread {
    @Override
    public void run() {
        for (int a = 0; a < 200; a++) {
            System.out.println(getName() + ":" + a);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Machine machine = new Machine ();
        machine .setName("t1");
        machine .start();
        System.out.println("main:join machine");
        machine .join(10);
        System.out.println("main:end");// 主线程运行结束
    }
}

打印结果(可能出现的情况):

main:join machine
t1:0
t1:1
t1:2
……
t1:55
main:end
t1:56
……

注:学习内容和代码,来源自《JAVA 面向对象编程》(第二版)作者:孙卫琴

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/831861.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号