多线程面试题目(1)

这篇具有很好参考价值的文章主要介绍了多线程面试题目(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

多线程基础

什么是多线程?多线程的优点与缺点?

多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务。

优点:可以提高 CPU 的利用率。在多线程程序中,一个线程必须等待的时候,CPU 可以运行其它的线程而不是等待,这样就大大提高了程序的效率。也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

缺点

  • 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多
  • 多线程需要协调和管理,所以需要CPU时间跟踪线程
  • 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题

创建线程的四种方式

继承Thread类,java是单继承
  • 定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体;
  • 创建Thread子类的实例,也就是创建了线程对象
  • 启动线程,调用线程的start()方法
public class CreateThread extends Thread{
    @Override
    public void run() {
        //获取线程名
        System.out.println(Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        CreateThread createThread = new CreateThread();
        //线程启动
        createThread.start();
    }
}
实现Runnable接口
  • 定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体。
  • 创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象。
  • 调用线程对象的start()方法来启动线程。
public class RunnableCreateThread implements Runnable{
    @Override
    public void run() {
        System.out.println("实现Runnable接口创建线程");
    }

    public static void main(String[] args) {
        new Thread(new RunnableCreateThread()).start();
    }
}

匿名内部类:

new Thread(new Runnable() {
    @Override
    public void run() {
 		// 调用资源方法,完成业务逻辑
    }
}, "your thread name").start();

lambda表达式:

new Thread(() -> {

}, "your thread name").start();
  • 实现Callable接口
  • 使用Executor工具类创建线程池
使用Callable和Future创建线程

与 Runnable 接口不一样,Callable 接口提供了一个 call() 方法作为线程执行体,call() 方法比 run() 方法功能要强大,比如:call() 方法可以有返回值、call() 方法可以声明抛出异常。

  • 创建实现 Callable 接口的类 CreateThread1;
  • 以 createThread1为参数创建 FutureTask 对象;
  • 将 FutureTask 作为参数创建 Thread 对象
  • 调用线程对象的 start() 方法
public class CreateThread1 implements Callable {

    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName());
        return "call() 方法可以有返回值、call() 方法可以声明抛出异常";
    }

    public static void main(String[] args) {
        //创建 FutureTask 对象
        FutureTask futureTask = new FutureTask<>(new CreateThread1());
        //创建线程并启动
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            Thread.sleep(1000);
            //获取返回值
            System.out.println("返回的结果是:" + futureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
基于线程池创建线程

(可去查看线程池的章节)

public class CreateThreadByExecutors implements Runnable {
    
    public static void main(String[] args) {
        ExecutorService service = Executors.newSingleThreadExecutor();
        CreateThreadByExecutors thread = new CreateThreadByExecutors();
        for (int i = 0; i < 10; i++) {
            service.execute(thread);
            System.out.println("=======任务开始=========");
            service.shutdown();
        }
    }

    @Override
    public void run() {
        System.out.println("hello Thread");
    }
}

Runnable和callable有什么区别

相同点:

  • 两个都是接口。
  • 都是编写多线程程序。
  • 都是采用Thread.start()启动程序。

区别:

  • Runnable的**run()方法无返回值,callable的call()**方法提供返回值用来表示任务运行的结果。
  • Runnable提供**run()方法,无法通过throws抛出异常,异常必须在run()方法内部处理。callable提供call()**方法,直接抛出异常。

线程的状态有哪些

线程5个状态:创建、就绪、运行、阻塞和死亡。

  • 新建(new):新创建了一个线程对象。
  • 就绪(runnable):线程对象创建后,当调用线程对象的start()方法,该线程可能处于运行状态,可能处于就绪状态,等待被线程调度选中,获取cpu使用权。
  • 运行(running):线程获取CPU权限执行
  • 阻塞(blocked):阻塞包含三种情况:等待阻塞,同步阻塞,其他阻塞
    • 等待阻塞:wait(),进入等待队列,需要notify唤醒(但notify唤醒的线程是随机的)
    • 同步阻塞:获取同步锁失败进入阻塞
    • 其他阻塞:sleep(),join(),发出IO请求
  • 等待(WAITING)
  • 定时等待(Timed Waiting)
  • 消亡(terminated):线程执行结束

线程的 run()和 start()有什么区别?

  1. 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,run()方法称为线程体。通过调用Thread类的start()方法来启动一个线程。
  2. start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start()只能调用一次。
  3. start()方法来启动一个线程,真正实现了多线程运行。调用start()方法无需等待run方法体代码执行完毕,可以直接继续执行其他的代码; 此时线程是处于就绪状态,并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, run()方法运行结束, 此线程终止。然后CPU再调度其它线程。
  4. run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。

为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用run() 方法?

  1. new 一个线程Thread,线程进入新建状态;调用start(),会启动一个线程并使线程进入就绪状态,当分配到时间片就可以开始工作了,start()会执行线程的相应准备工作,然后自动执行run()方法的内容,这是真正的多线程工作。
  2. 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。文章来源地址https://www.toymoban.com/news/detail-802358.html

到了这里,关于多线程面试题目(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java面试汇总——jvm篇

    目录 JVM的组成: 1、JVM 概述(⭐⭐⭐⭐) 1.1 JVM是什么? 1.2 JVM由哪些部分组成,运行流程是什么? 2、什么是程序计数器?(⭐⭐⭐⭐) 3、介绍一下Java的堆(⭐⭐⭐⭐) 4、虚拟机栈(⭐⭐⭐⭐) 4.1 什么是虚拟机栈? 4.2 垃圾回收是否涉及栈内存? 4.3 栈帧内存分配越大越好吗? 4.4

    2024年01月17日
    浏览(42)
  • java八股文面试[JVM]——JVM内存结构

    参考: JVM学习笔记(一)_卷心菜不卷Iris的博客-CSDN博客 JVM 是运行在操作系统之上的,它与硬件没有直接的交互 JVM内存结构:   方法区:存储已被虚拟机加载的类元数据信息(元空间) 堆:存放对象实例,几乎所有的对象实例都在这里分配内存 虚拟机栈:虚拟机栈描述的是

    2024年02月12日
    浏览(47)
  • JAVA 学习 面试(三)JVM篇

    JAVA虚拟机(JVM) JDK、JRE、JVM的关系 JDK JRE = Java虚拟机 + Java核心类库 JVM组成结构: (1)类加载器 (2)运行时数据区 (3)执行引擎 (4)本地库接口 类加载器 Java程序运行的时候,编译器将Java文件编译成平台无关的Java字节码文件(.class),接下来对应平台JVM对字节码文件进

    2024年01月22日
    浏览(52)
  • 面试最常被问的 Java 后端题目及参考答案

    一、Java 基础篇 1. Object 有哪些常用方法?大致说一下每个方法的含义 2. Java 创建对象有几种方式? 3. 获取一个类对象的方式有哪些? 4. ArrayList 和 LinkedList 的区别有哪些? 5. 用过 ArrayList 吗?说一下它有什么特点? 6. 有数组了为什么还要搞个 ArrayList 呢? 7. 说说什么是 fai

    2024年02月12日
    浏览(43)
  • 3.Java面试题—JVM基础、内存管理、垃圾回收、JVM 调优

    一篇文章掌握整个JVM,JVM超详细解析!!! JVM (Java虚拟机) 是运行 Java 字节码 的 虚拟机 。 JVM 针对 不同系统 有 特定实现 ( Windows 、 Linux 等),目的是 同样的代码 在 不同平台 能运行出 相同的结果 。 Java 语言 要经过 编译 和 解释 两个步骤: 编译 :通过 编译器 将 代码 一

    2024年02月15日
    浏览(50)
  • JVM篇--Java内存区域高频面试题

    首先我们要知道java堆空间的产生过程: 即当通过java命令启动java进程的时候,就会为它分配内存,而分配内存的一部分就会用于创建堆空间,而当程序中创建对象的时候 就会从堆空间来分配内存,所以堆空间存放的主要是对象和数组; 而GC 其实说白了就是java虚拟机回收对象

    2024年02月01日
    浏览(52)
  • JAVA工程师面试专题-JVM篇

    目录 一、运行时数据区 1、说一下JVM的主要组成部分及其作用? 2、说一下 JVM 运行时数据区 ? 3、说一下堆栈的区别 4、成员变量、局部变量、类变量分别存储在什么地方? 5、类常量池、运行时常量池、字符串常量池有什么区别? 6、JVM为什么使用元空间替换永久代 二、垃

    2024年02月21日
    浏览(46)
  • java八股文面试[JVM]——元空间

    JAVA8为什么要增加元空间 为什么要移除永久代?    知识来源: 【2023年面试】JVM8为什么要增加元空间_哔哩哔哩_bilibili

    2024年02月11日
    浏览(52)
  • java八股文面试[JVM]——垃圾回收

    参考:JVM学习笔记(一)_卷心菜不卷Iris的博客-CSDN博客 GC垃圾回收 面试题: JVM内存模型 以及分区,需要详细到每个区放什么 堆里面的分区:Eden,survival from to,老年代,各自的特点。 GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方 针

    2024年02月11日
    浏览(47)
  • 大厂面试题一文讲通jvm,Java虚拟机高频面试题

    薪资范围:6-16K 一个类完整的生命周期,会经历五个阶段,分别为: 加载、连接、初始化、使用 、和 卸载 。其中的连接又分为 验证、准备 和 解析 三个步骤。如下图所示 加载(Loading) 简单一句话概括,类的加载阶段就是: 找到需要加载的类并把类的信息加载到jvm的方法

    2024年01月18日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包