首页 > 编程语言 >Java并发编程常见面试题

Java并发编程常见面试题

时间:2024-10-11 19:51:41浏览次数:8  
标签:面试题 Java Thread 编程 死锁 线程 println 方法 resource2

1. 简要描述 线程 和 进程 的关系,区别以及优缺点

  • 进程: 操作系统为程序分配的资源集合,每个进程拥有独立的地址空间。
  • 线程: 同一个进程可以包含多个线程,他们共享线程的地址空间资源
  • 一个进程中可以有多个线程,多个线程共享进程的方法区资源,但是每个线程有自己的程序计数器、虚拟机栈本地方法栈
  • 总的来说,线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。

2. 线程间同步的锁机制

常见的线程同步锁机制包括:锁(如 互斥锁、读写锁)、信号量、条件变量、以及高级别的工具如 CyclicBarrier、CountDownLatch。

3. Java线程 和 操作系统的线程有啥区别

JDK1.2之前,Java线程是一种用户级线程(用户线程),也就是说JVM 自己模拟了多线程的运行,而不依赖操作系统。
由于不能直接使用操作系统提供的功能比如异步IO、只能在一个内核线程上运行,无法利用多核,所以,JDK1.2之后,Java线程基于原生线程实现,也就是说JVM直接使用操作系统原生的内核级线程(内核线程)来实现Java线程,由操作系统内核进行线程的调度和管理
总的来说,现在的Java线程本质其实就是操作系统的线程。

用户线程: 由用户空间程序管理和调度的线程,运行在用户空间(专门给应用程序使用)
内核线程: 由操作系统内核管理和调度的线程,运行在内核空间(只有内核程序可以访问)
区别: 用户线程创建和切换成本低,但不可以利用多核。内核态线程,创建和切换成本高,可以利用多核。

4. 为什么程序计数器、虚拟机栈和本地方法栈是线程私有的呢?为什么堆和方法区是线程共享的呢

程序计数器:线程切换后能恢复到正确的执行位置

虚拟机栈: 存储局部变量、操作数栈、常量池引用

本地方法栈: 存储Java虚拟机执行的Java方法(字节码)

为了保证线程中的布局变量不被其他线程访问到,虚拟机栈本地方法栈 是线程私有的

堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,主要用于存放新创建的对象 (几乎所有对象都在这里分配内存),方法区主要用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

5. 线程的生命周期和状态

线程生命周期内6种状态

  • NEW: 初始状态,线程被创建出来但没有被调用 start()

  • RUNNABLE: 运行状态,线程被调用了 start()等待运行的状态。

  • BLOCKED:阻塞状态,需要等待锁释放。

  • WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)。

  • TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像 WAITING 那样一直等待。

  • TERMINATED:终止状态,表示该线程已经运行完毕

线程在生命周期中并不是固定处于某个状态,而是随着代码的执行在不同的状态之间切换。

6. Thread.sleep() & Object.wait()

共同点: 都可以暂停线程的执行

区别:

  • sleep() 方法没有释放锁,而wait()释放锁
  • wait() 通常被用于线程间交互/通信,sleep()通常被用于暂停执行。
  • wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify()或者 notifyAll() 方法。sleep()方法执行完成后,线程会自动苏醒,或者也可以使用 wait(long timeout) 超时后线程会自动苏醒。
  • sleep()Thread 类的静态本地方法,wait()则是Object` 类的本地方法。

wait()是让获得对象锁的进程实现等待,会自动释放当前线程占有的对象锁.每个对象(Object)都拥有对象锁,既然要释放当前线程占有的对象锁并让其进入 WAITING 状态,自然是要操作对应的对象(Object)而非当前的线程(Thread)。

7. 可以直接调用Thread类的run方法吗?

直接执行 run() 方法,会把 run() 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它。调用 start() 方法方可启动线程并使线程进入就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,直接执行 run() 方法的话,不会以多线程的方式执行。

并发 和 并行 的区别

  • 并发:两个及两个以上的作业在同一 时间段内执行。(区间时段内)
  • 并行:两个及两个以上的作业在同一时刻执行。(同时)

同步 和 异步 的区别

  • 同步:发出一个调用后,在没有得到结果之前,该调用就不可以返回,一直等待。
  • 异步:调用在发出之后,不用等待返回结果,该调用直接返回。

8. 线程不安全

并发编程问题 —> 内存泄露、死锁、线程不安全。

  • 线程安全:不管有多少个线程同时访问,都能保证这份数据的正确性和一致性。
  • 线程不安全:多个线程同时访问时可能会导致数据混乱、错误或者丢失。

9. 死锁

多个线程同时被阻塞,它们中的一个或者全部都在等在某个资源被释放,由于线程被无限期地阻塞,因此程序不可能正常终止。

例子:线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。

如何检测死锁?

  • 使用jmapjstack等命令查看 JVM 线程栈和堆内存的情况。如果有死锁,jstack 的输出中通常会有 Found one Java-level deadlock:的字样,后面会跟着死锁相关的线程信息。另外,实际项目中还可以搭配使用topdffree等命令查看操作系统的基本情况,出现死锁可能会导致 CPU、内存等资源消耗过高。

  • 采用 VisualVM、JConsole 等工具进行排查。

如何预防死锁

  • 破坏请求与保持条件:一次性申请所有资源。
  • 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
  • 破坏循环等待条件:按某一顺序申请资源,反序释放资源。

如何避免死锁

// 未避免死锁
public class DeadLockDemo {
    private static Object resource1 = new Object();//资源 1
    private static Object resource2 = new Object();//资源 2

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resource1) {
                System.out.println(Thread.currentThread() + "get resource1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource2");
                synchronized (resource2) {
                    System.out.println(Thread.currentThread() + "get resource2");
                }
            }
        }, "线程 1").start();

        new Thread(() -> {
            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get resource2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource1");
                synchronized (resource1) {
                    System.out.println(Thread.currentThread() + "get resource1");
                }
            }
        }, "线程 2").start();
    }
}
// 避免死锁
new Thread(() -> {
            synchronized (resource1) {
                System.out.println(Thread.currentThread() + "get resource1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource2");
                synchronized (resource2) {
                    System.out.println(Thread.currentThread() + "get resource2");
                }
            }
        }, "线程 2").start();
// 无论是哪个线程,都应该首先获取 resource1 的锁,然后再获取 resource2 的锁,则可以避免死锁。

标签:面试题,Java,Thread,编程,死锁,线程,println,方法,resource2
From: https://blog.csdn.net/m0_74119287/article/details/142727443

相关文章

  • Java并发编程-线程池
    ThreadLocal应用场景:两个线程争执一个资源。解决问题:实现每个线程绑定自己的专属本地变量,可以将ThreadLocal类理解成存放数据的盒子,盒子中存放每个线程的私有数据。线程池的用途选择快速响应用户请求:比如说用户查询商品详情页,会涉及查询商品关联的一系列信息如价格、优......
  • Java String.valueOf 和 toString的区别
    String.valueOf()和toString()都是Java中用于获取字符串表示的方法,但它们的使用场景和实现方式有所不同。以下是它们之间的主要区别:1.方法来源String.valueOf(Objectobj):是String类的静态方法,接受一个对象作为参数。如果传入的对象为null,它会返回字符串"null"。......
  • JavaScript的内置对象有哪些?
    一、内置对象1、概念​JavaScript中的对象共分为3种:自定义对象、浏览器对象和内置对象。之前我们自己创建的对象都属于自定义对象,而内置对象又称为API,是指JavaScript语言自己封装的一些对象,用来提供一些常用的基本功能,来帮助我们提高开发速度,例如:数学-Math、日期-Date......
  • Java中反射的机制
    反射目录反射反射的概念反射的作用反射的原理直接使用类使用反射总结什么情况下使用反射反射的优缺点反射是否真的会让你的程序性能降低?反射的概念反射(Reflection)是Java的一种特性,它可以让程序在运行时获取自身的信息,并且动态地操作类或对象的属性、方法和构造器等。通过反......
  • 递归算法的时间复杂度(通过一道面试题来讲解)
    本篇通过一道简单的面试题,逐步分析递归算法的时间复杂度,最后找到最优解同一道题目,同样使用递归算法,既可以写出时间复杂度为O(n)的代码,也可以写出时间复杂度为O(logn)的代码。why?这是因为对递归算法的时间复杂度理解不够深入。下面通过一道面试题,来逐步分析递归算法的时间复......
  • JVM系列1:深入分析Java虚拟机堆和栈及OutOfMemory异常产生原因
    JVM系列1:深入分析Java虚拟机堆和栈及OutOfMemory异常产生原因前言JVM系列文章如无特殊说明,一些特性均是基于HotSpot虚拟机和JDK1.8版本讲述。下面这张图我想对于每个学习Java的人来说再熟悉不过了,这就是整个JDK的关系图: 从上图我们可以看到,JavaVirtualMachine位于最底......
  • [Java原创精品]基于Springboot+Vue的仿小红书博客论坛系统,社交媒体平台,含DFA敏感词过
    项目提供:完整源码+数据库sql文件+数据库表对应Excel文件项目获取看主......
  • java算法OJ(2)链表
    目录1.前言2.正文2.1合并俩个有序链表2.1.1题目描述2.1.2示例2.1.3代码2.2俩数相加2.2.1题目描述2.2.2示例2.2.3代码2.3分割链表2.3.1题目描述2.3.2示例2.3.3代码3.小结1.前言哈喽大家好吖,今天来对先前学习的链表进行巩固,做几道算法题,如果大家有更加优良的......
  • Java中的专有名词——JVM、JRE、JDK到底是什么关系
            相信刚开始学习Java的同学一定见过“JVM、JDK、JRE”这三个专有名词,那他们到底代表的是什么,三者之间又有何种关系呢?        下面我们先来介绍一下三者:1.JVM    JVM:Java虚拟机(JavaVirtualMachine,JVM)是运行Java字节码的虚拟机。JVM有......
  • 实验一,现代C++编程初体验
    一、实验目的 体验C++的标准库,算法库用法。数据表示,分支循环,函数和标准库等,编程解决简单基础问题。二、实验准备 第二章C++语言简单设计第三章函数第九章函数模板 三、实验内容 1.实验任务1代码:1#include<iostream>2#include<string>3#include<vector>......