首页 > 编程语言 >Java面试题笔记-多线程篇

Java面试题笔记-多线程篇

时间:2024-02-27 19:46:42浏览次数:25  
标签:状态 面试题 Java 获取 任务 线程 多线程 方法

创建线程的几种方式

  1. 继承Thread类,重写run方法

  2. 实现Runnable接口,实现run方法

  3. 实现Callable,实现call方法,配合FutureTask获取线程返回结果

  4. 通过ThreadPoolExecuter线程池获取线程资源

这几种方法的底层都是Runnable,Thread是Runnable接口的实现类,Callable配合FutureTask使用,是Runnable的实现类,线程池提供的工作线程也是Runnable的实现类

线程状态

这个问题可以从两个方面回答:

  1. 新建 → 【就绪|运行】 → 等待 → 结束 五种状态,这个是操作系统级别的线程状态

    • 新建:new Thread(),创建线程对象后在启动线程之前为新建状态
    • 就绪:thread.start(),启动线程后线程会进入就绪状态,因为线程的执行是需要CPU调度的,所以会先进入就绪状态
    • 运行:CPU调度时为运行状态,CPU不可能一直停留在当前线程,所以该阶段会在【就绪|运行】状态中反复切换
    • 等待:Object.wait() thread.join() Thread.sleep(),当线程由于某些原因暂停运行时为等待状态
    • 结束:线程工作结束
  2. 新建 → 运行→ 【阻塞|等待|超时等待】 → 结束 六种状态,这个是Java线程枚举类中规定的几种状态

    • 新建:同上
    • 运行:在Java中执行thread.start()方法后就属于运行状态,不考虑CPU调度的问题
    • 阻塞:BLOCKED,在获取到线程锁之前无法执行目标代码,此时线程处于阻塞状态
    • 等待:WAITING,例如Object.wait()让线程进入等待状态,需要其他线程唤醒后才可继续执行
    • 超时等待:TIMED_WAITING,例如Thread.sleep()让线程进入睡眠状态,规定时间后自动唤醒

停止线程的方法

  1. 可以通过Thread.stop()方法停止线程,不过由于该方法过于暴力执行后强制停止线程的运行,可能会导致一些不可预计的问题(例如资源未释放),虽然有效但目前已被废弃不推荐使用

  2. 可以在线程对象中维护个成员变量作为标志位,通过循环判断该标志位的状态,如果标志位被修改就停止线程运行,该方法可以在停止线程前进行一些善后工作

  3. 可以使用thread.interrupt()方法结束线程,该方法不同于Thread.stop()强制停止,而是类似于第二种方法底层维护一个boolean类型的变量,通常来说interrupt需要配合sleep、wait、join等方法响应停止才会产生效果,可以通过thread.isInterrupted()方法查看标志位的值,默认为false,为true即为停止状态

wait方法和sleep方法的区别

  1. wait方法是Object对象提供的方法,而sleep是Thread提供的静态方法

  2. wait方法是线程等待状态,需要其他线程唤醒后才可以继续执行,sleep方法是超时等待状态,对应时间结束后会自动唤醒并继续执行

  3. wait方法必须在线程持有锁时才能执行,而sleep无论是否持有锁都可以执行

  4. wait方法等待时会释放锁资源供其他线程使用,而sleep会带着锁一起进入等待状态

Java中都有哪些锁

  1. 重入锁与非重入锁

    • 重入锁:重入锁又叫递归锁,指在已经拥有A锁的情况下执行另一处需要A锁的代码,可以顺利执行不会被阻塞,底层会记录对该锁的引用次数,Java中提供的syncronized、ReentrantLock,ReentrantReadWriteLock都属于重入锁
    • 非重入锁:非重入锁是指在已经拥有A锁的情况下执行另一处需要A锁的代码,被阻塞无法执行,必须释放后重新获取才可继续执行,目前Java并没有提供可直接使用的非重入锁
  2. 乐观锁与悲观锁

    • 悲观锁:获取不懂锁资源时线程会阻塞,等待其他线程释放锁后在尝试去获取锁
    • 乐观锁:获取不到锁资源时会再次获取,直至获取成功
  3. 公平锁与非公平锁,假设有个任务列表,线程A和线程B负责执行:

    • 非公平锁:线程A和线程B竞争,线程A获取到了锁资源执行业务,线程B等待,A执行完成释放锁后会重新参与竞争,可能会多次连续获取到锁,导致B线程始终等待,这种就属于非公平锁,线程B的状态又被称为饥饿线程
    • 公平锁:线程A和线程B竞争,线程A获取到了锁资源执行业务,线程B等待,A执行完成释放锁后会排队重新参与竞争,等B释放锁后才会轮到A获取锁,保证任务的公平分配
  4. 互斥锁与共享锁,指的的ReentrantReadWriteLock

    • 互斥锁:互斥锁又被称为独占锁,只能有一个线程获取该锁并执行任务
    • 共享锁:共享锁可以被多个线程获取并执行代码,通常需要配合互斥锁一起使用,读写锁就是经典案例

synchronized和Lock的区别

  1. syncronized是Java中提供的关键字,可以作用在方法上,也可以在代码中直接使用,在代码中直接使用为对象锁,需要手动维护一个锁对象,作用在成员方法上会以该对象为锁,作用在静态方法上会以该类为锁;而Lock锁是Java提供的类,需要new对象后使用

  2. syncronized锁的作用范围是大括号,无论是类锁还是对象锁都是基于这个括号自动获取和释放锁,而Lock锁需要手动new对象后通过lock.lock()获取锁,然后通过lock.unlock()释放锁,还可以获取锁的状态,以及超时获取锁等等,相比syncronized更灵活方便

  3. syncronized锁默认为独享的非公平锁,而Lock锁是接口类,下面有很多实现,可以实现独享锁共享锁,以及公平锁和非公平锁,功能更强大

  4. 底层实现原理不同,技术太浅后面学习JVM后再深入了解

Java中提供了哪些线程池

  1. fixedThreadPool是定长的线程池,构建该线程池需要传入一个int值分别作为核心线程数和最大线程数

  2. singleThreadExecutor是单线程池,该线程池中有且仅有一个工作线程,多出的任务都会存在任务队列中

  3. cachedThreadPool是缓存线程池,正常流程是线程池接收到任务后交给线程处理,没有空闲线程时会存储到任务队列,该线程池没有核心线程,任务是直接进入队列然后初始化工作线程去处理,且工作线程最大数量没有限制,为Integer.MAX_VALUE

  4. scheduleThreadPool是定时线程池,它可以让任务等待至规定时间后执行,也可以让某一个任务周期性执行

  5. workStealingPool不同与前几个线程池,前几个都是多个线程从队列中获取任务,该线程池中每个线程都有一个自己的队列,底层使用了Fork/Join模式,当有空闲线程时时会帮助其他线程分担任务

为什么不推荐使用Java提供的线程池

因为Java提供的线程池的参数配置都是固定的,这些线程池对于任务数量和线程数量并没有做合适的限制,任务数量过多时可能会导致堆内存溢出,而线程数量过多时可能会导致栈内存溢出,一般推荐自定义线程池

构建线程池的参数列表主要有哪些

Java提供的线程池底层都是通过ThreadPoolExecutor构建出来的,核心参数包含:

  • int corePoolSize 核心线程池数,该线程不会被回收

  • int maximumPoolSize 最大线程数,当队列中任务堆积时会动态创建线程进行工作,最大线程数不得超过这里的规定值

  • long keepAliveTime 线程超时时间,当动态创建的线程超过规定时间没有工作时就会被回收

  • TimeUnit unit 线程超时时间的单位

  • BlockingQueue<Runnable> workQueue 任务队列

  • ThreadFactory threadFactory 线程工厂,负责创建线程

  • RejectedExecutionHandler handler 线程池对于任务的拒绝策略

线程池的任务拒绝策略有哪些

  • AbortPolicy:当线程池无法处理任务时,直接抛出异常

  • CallerRunsPolicy:当线程池无法处理任务时,将任务交给调用方处理

  • DiscardPolicy:当线程池无法处理任务时,直接将任务丢弃

  • DiscardOldestPolicy:当线程池无法处理任务时,将队列中最早的任务丢掉,加入当前任务

标签:状态,面试题,Java,获取,任务,线程,多线程,方法
From: https://www.cnblogs.com/hanzhe/p/18036197

相关文章

  • 面试题(三)—— 跨域
    一、什么是跨域1、跨域的产生在Web开发中,一个网页请求另一个域(域名、协议、端口号任一不同)的资源,就会发生跨域。2、跨域请求跨域请求是指在浏览器中执行的请求,其目标资源的域名、协议或端口与当前页面不同。3、跨域资源共享(CORS)跨域资源共享(CORS)是一种机制,它允许在一个源(域......
  • java面向对象-第一步
    面向过程&面向对象面向过程思想◆步骤清晰简单,第一步做什么,第二步做什么….◆面对过程适合处理一些较为简单的问题◆面向对象思想◆物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。面......
  • Java基础-String字符串和数组
    1.String基础:字符串是编程时经常用到的一种数据类型。Java中使用String类和StringBuilder类来封装字符串。String类定义不变字符串,StringBuffer类则用于可变字符串处理。换句话说,String类创建的字符串时不会改变的,而StringBuffer类创建的字符串可以修改。字符串的声明与创建:1.......
  • Java基础-面向对象概述
    本章重点针对面向对象的三大特征:继承、封装、多态进行详细的讲解。另外还包括抽象类、接口、内部类等概念。很多概念对于初学者来说,更多的是先进性语法性质的了解。1.面向对象-继承:1.继承的实现:继承通过如下格式实现:class子类名extends父类名[implements<接口名>]{}......
  • Java基础-面向过程和面向对象
    面向过程和面向对象都是对软件分析、设计和开发地一种思想,它指导着人们以不同的方式去分析、设计和开发软件。这两种思想是相辅相成的。面向过程:使用面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。这个思想适合简单任务,不需要过多......
  • Java基础-常用类
    一、字符串相关的类1.String的特性String类:代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。String是一个final类,代表不可变的字符序列。字符串是常量,用双引号引起来表示。他们的值在创建之后不能更改。String对象的字符内容是存储在一个字符数......
  • java 实现根据word模板生成word文件 word转pdf
    最近做项目要求生成word文件及PDF文件,生成word文件时其中内容要根据不同公司提供的内容动态替换里面的值。参考了很多之后选择用word模板生成word文件。其中主要参考:https://www.cnblogs.com/suzan/p/10577738.html 简单的word模板:https://files.cnblogs.com/files/blogs/8095......
  • 面试题以及一些问题概述
    1数据库三大范式是什么数据库的三大范式是指关系数据库设计中的三个规范化级别,用于规范化数据库中的数据结构,提高数据的一致性和减少数据冗余。这三大范式分别是:1.第一范式(1NF):要求数据库表中的每个字段都是原子性的,不可再分。也就是说,每个字段中的数据不能包含多个值或多个属......
  • 面试题(一)—— CSS 盒模型
    一、什么是 CSS盒模型CSS盒模型是指在网页中,每个元素都被看作是一个矩形的盒子,这个盒子包含了元素的内容(content)、内边距(padding)、边框(border)和外边距(margin)。 二、标准盒模型与怪异盒模型1、box-sizing两个常用参数:content-box:默认值。标准盒模型border-box:怪异盒模......
  • Java中使用Graphics2D实现图片添加文字/图片水印
    场景java实现给图片添加水印实现步骤:获取原图片对象信息(本地图片或网络图片)添加水印(设置水印颜色、字体、坐标等)处理输出目标图片。注:博客:https://blog.csdn.net/badao_liumang_qizhi实现1、新建工具类 importorg.apache.commons.lang3.StringUtils;importjavax.im......