首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面试系列之-线程其他相关(JAVA基础)

面试系列之-线程其他相关(JAVA基础)

作者头像
用户4283147
发布于 2023-08-21 12:18:50
发布于 2023-08-21 12:18:50
17100
代码可运行
举报
文章被收录于专栏:对线JAVA面试对线JAVA面试
运行总次数:0
代码可运行

线程的调度模型/线程的优先级

线程的调度模型

目前主要分为两种:分时调度模型和抢占式调度模型;

分时调度模型 系统平均分配CPU的时间片,所有线程轮流占用CPU,即在时间片调度的分配上所有线程“人人平等”;

抢占式调度模型

系统按照线程优先级分配CPU时间片。优先级高的线程优先分配CPU时间片,如果所有就绪线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些。由于目前大部分操作系统都是使用抢占式调度模型进行线程调度,Java的线程管理和调度是委托给操作系统完成的,与之相对应,J‍match‍ava的线程调度也是使用抢占式调度模型,因此Java的线程都有优先级;

线程的优先级

Thread实例的priority属性默认是级别5,对应的类常量是NORM_PRIORITY,优先级最大值为10,最小值为1;Java中使用抢占式调度模型进行线程调度,priority实例属性的优先级越高,线程获得CPU时间片的机会就越多,但也不是绝对的;

线程相关操作方法

线程的sleep操作

sleep的作用是让目前正在执行的线程休眠,让CPU去执行其他的任务。从线程状态来说,就是从执行状态变成限时阻塞状态。Sleep()方法定义在Thread类中,是一组静态方法。当线程睡眠时间满后,线程不一定会立即得到执行,因为此时CPU可能正在执行其他的任务,线程首先进入就绪状态,等待分配CPU时间片以便有机会执行;

线程的interrupt操作

Thread的interrupt()方法,此方法本质不是用来中断一个线程,而是将线程设置为中断状态。当我们调用线程的interrupt()方法时,它有两个作用:

(1)如果此线程处于阻塞状态(如调用了Object.wait()方法),就会立马退出阻塞,并抛出InterruptedException异常,线程就可以通过捕获InterruptedException来做一定的处理,然后让线程退出。更确切地说,如果线程被Object.wait()、Thread.join()和Thread.sleep()三种方法之一阻塞,此时调用该线程的interrupt()方法,该线程将抛出一个InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早终结被阻塞状态。

(2)如果此线程正处于运行之中,线程就不受任何影响,继续运行,仅仅是线程的中断标记被设置为true。所以,程序可以在适当的位置通过调用isInterrupted()方法来查看自己是否被中断,并执行退出操作。如果线程的interrupt()方法先被调用,然后线程开始调用阻塞方法进入阻塞状态,InterruptedException异常依旧会抛出。如果线程捕获InterruptedException异常后,继续调用阻塞方法,将不再触发;

线程的join操作

线程合并:假设有两个线程A和B。现在线程A在执行过程中对另一个线程B的执行有依赖,具体的依赖为:线程A需要将线程B的执行流程合并到自己的执行流程中(至少表面如此),这就是线程合并,被动方线程B可以叫作被合并线程;

(1)执行没有时限(timeout)参数的thread.join()调用:在线程合并场景中,若线程A调用B.join()去合入B线程,则在B执行期间线程A处于WAITING状态,一直等线程B执行完成。

(2)执行没有时限(timeout)参数的object.wait()调用:指一个拥有object对象锁的线程,进入相应的代码临界区后,调用相应的object的wait()方法去等待其“对象锁”(Object Monitor)上的信号,若“对象锁”上没有信号,则当前线程处于WAITING状态;

线程的yield操作

线程的yield(让步)操作的作用是让目前正在执行的线程放弃当前的执行,让出CPU的执行权限,使得CPU去执行其他的线程。处于让步状态的JVM层面的线程状态仍然是RUNNABLE状态,但是该线程所对应的操作系统层面的线程从状态上来说会从执行状态变成就绪状态。线程在yield时,线程放弃和重占CPU的时间是不确定的,可能是刚刚放弃CPU,马上又获得CPU执行权限,重新开始执行。yield()方法是Thread类提供的一个静态方法,它可以让当前正在执行的线程暂停,但它不会阻塞该线程,只是让线程转入就绪状态。yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次;

  1. 线程的daemon操作
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DaemonDemo{
    public static final int SLEEP_GAP = 500; //每一轮的睡眠时长
    public static final int MAX_TURN = 4; //用户线程执行轮次
    //守护线程实现类
    static class DaemonThread extends Thread{
        public DaemonThread(){
            super("daemonThread");
        }
        public void run(){
            Print.synTco("--daemon线程开始.");
            for (int i = 1; ; i++) //死循环{
                Print.synTco("--轮次:" + i);
                Print.synTco("--守护状态为:" + isDaemon());
                // 线程睡眠一会,500毫秒
                sleepMilliSeconds(SLEEP_GAP);
            }
        }
    }
    public static void main(String args[]) throws InterruptedException{
        Thread daemonThread = new DaemonThread();
        daemonThread.setDaemon(true);
        daemonThread.start();
        //创建一条用户线程,执行4轮
        Thread userThread = new Thread(() ->{
          Print.synTco(">>用户线程开始.");
          for (int i = 1; i <= MAX_TURN; i++){
            Print.synTco(">>轮次:" + i);
            Print.synTco(">>守护状态为:" + getCurThread().isDaemon());
            sleepMilliSeconds(SLEEP_GAP);
           }
            Print.synTco(">>用户线程结束.");
        }, "userThread");
        //启动用户线程
        userThread.start();
        Print.synTco(" 守护状态为:" + getCurThread().isDaemon());
        Print.synTco(" 运行结束.");
    }
}

线程中断interrupt()/interrupted()/isInterrupted()

interrupt()

Thread.interrupt()方法: 作用是中断线程。将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序本身。线程会不时地检测这个中断标示位,以判断线程是否应该被中断(中断标示值是否为true)。它并不像stop方法那样会中断一个正在运行的线程;

如果线程被Object.wait、Thread.join、Thread.sleep三种方法之一阻塞,此时调用该线程的interrupt()方法,那么该线程将抛出一个 InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用 interrupt()将不起作用,直到执行到wait()、sleep()、join()时,才马上会抛出 InterruptedException;

interrupted()

测试当前线程是否已经中断(静态方法),如果连续调用该方法,则第二次调用将返回false。在api文档中说明interrupted()方法具有清除状态的功能,执行后具有将状态标识清除为false的功能;

内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态;测试当前线程是否已经中断(静态方法),返回的是上一次的中断状态,并且会清除该状态,所以连续调用两次,第一次返回true,第二次返回false;

isInterrupted()

测试线程是否已经中断,但是不能清除状态标识;isInterrupted()是实例方法,是调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态测试线程当前是否已经中断,但是不能清除状态标识;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 对线JAVA面试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
并发编程1:全面认识 Thread
本文介绍了Java编程中线程的创建方式、启动方式、线程池的创建和线程池的使用,以及线程池的拒绝策略。同时,本文还介绍了线程的 run() 和 start() 方法的区别以及线程的中断和终止等知识点。
张拭心 shixinzhang
2018/01/05
8050
并发编程1:全面认识 Thread
高并发Java(2):多线程基础
使用线程的原因是,进程的切换是非常重量级的操作,非常消耗资源。如果使用多进程,那么并发数相对来说不会很高。而线程是更细小的调度单元,更加轻量级,所以线程会较为广泛的用于并发设计。
用户5640963
2019/07/25
5450
高并发Java(2):多线程基础
21.1 Java 多线程编程基础
进程: 一个正在执行的程序。每个进程执行都有一个执行顺序,该顺序是一个执行路径,或叫一个控制单元。一个进程至少有一个线程。
acc8226
2022/05/17
3250
21.1 Java 多线程编程基础
Java并发编程基础篇(一)之线程
Java并发编程基础篇(一)之线程
Java架构师必看
2021/04/13
5410
Java并发编程基础篇(一)之线程
多线程快速入门与多线程与线程高级(多线程实战【三】)
初始化状态 就绪状态 运行状态 死亡状态 阻塞状态 超时等待 等待状态
高大北
2022/06/14
3790
多线程快速入门与多线程与线程高级(多线程实战【三】)
(十二)yield、notify、notifyAll、sleep、join、wait(三)
Object.wait(long)要跟Object.notify()/notifyAll()搭配使用。
HaC
2020/12/30
8360
多线程编程理论知识
是操作系统进行资源分配的最小单位,资源包括CPU、内存空间、磁盘IO等。一个进程是一个独立的运行环境,它可以被看做是一个应用(Android中,一个应用程序就是一个独立的进程)
ruochen
2021/11/25
3990
Java并发编程之基础
使用FutureTask可以用泛型指定线程的返回值类型(Runnable的run方法没有返回值)
Java微观世界
2025/01/21
1070
Java并发编程之基础
多线程基础
<font color="red">中央处理器</font>: 作为计算机系统的运算和控制的核心,是信息处理、程序运行的最终执行单元。
程序员NEO
2023/09/30
2620
多线程基础
【Java并发系列】Java线程基础
线程的runnable状态是从虚拟机的角度来看的,表示这个线程正在运行。但是处于Runnable状态的线程不一定真地消耗CPU。处于Runnable的线程只能说明该线程没有阻塞在java的wait或者sleep方法上,同时也没等待在锁上面。但是如果该线程调用了本地方法,而本地方法处于等待状态,这个时候虚拟机是不知道本地代码中发生了什么,此时尽管当前线程实际上也是阻塞的状态,但实际上显示出来的还是runnable状态,这种情况下是不消耗CPU的。
章鱼carl
2022/03/31
2950
【Java并发系列】Java线程基础
Java并发编程基础
在不同的 JVM 以及 操作系统 上,线程规划会存在差异,有些操作系统甚至会忽略对线程优先级的设定。 线程优先级不能作为程序正确性的依赖,因为操作系统可以完全不用理会 Java 线程对于优先级的设定。
103style
2022/12/19
2340
Java并发编程基础
Java-JUC
FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况
小简
2023/01/30
4230
相关推荐
并发编程1:全面认识 Thread
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档