面试提问--线程&线程池

1.创建线程有哪几种??
据官方注释只有两种,打开Thread看官方注释;如图
在这里插入图片描述

  • 第一种:直接new Thread
public static void main(String[] args) {
        new PrimeThread().start();
    }

    static class PrimeThread extends Thread {
        @Override
        public void run() {
            super.run();
        }
    }
  • 第二种:实现Runnable
  Runnable runnable=new Runnable() {
           @Override
           public void run() {

           }
       };
      new  Thread(runnable).start();

说三种的让面试官好好看看注释 哈哈

2.通过Callable和FutureTask创建线程的原理??
这是网上说的第三种创建线程的方式,其实就是FutureTask实现Runnable接口,本质还是Runnable,所以面试的时候完全可以说就只有两种方式创建线程。Callable使用代码如下

       Callable<Integer> callable=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 1;
            }
        };
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        new Thread(futureTask,"FutureTask").start();
public class FutureTask<V> implements RunnableFuture<V> {}
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

通过Callable可以拿到线程执行的返回值,如下

 Integer i= futureTask.get();

3.如何保证线程依次执行??

  • Thread.join()
    比如在线程1 中调用了线程2 的 join(),直到线程1执行完毕后,才会继续执行线程2;代码演示如图

    在这里插入图片描述

  • 使用CountDownLatch

在这里插入图片描述

  • 使用阻塞队列(BlockingQueue)
    LinkedBlockingQueue中维持两把锁,一把锁用于入队,一把锁用于出队,这也就意味着,同一时刻,只能有一个线程执行入队,其余执行入队的线程将会被阻塞;同时,可以有另一个线程执行出队,其余执行出队的线程将会被阻塞。

在这里插入图片描述

4.线程池有使用过吗,请简述下他的原理??

首先来看看线程池的构造方法

   public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
  • corePoolSize:核心线程池的数量,同时能执行的线程数量
  • maximumPoolSize:最大线程数,允许的最大数量
  • keepAliveTime:线程的存活时间。当线程池里的线程数大于corePoolSize时,如果等了keepAliveTime时长还没有任务可执行,则线程退出。
  • unit:keepAliveTime时间的单位,例如 1*TimeUnit.HOURS
  • workQueue:阻塞队列,提交的线程会被塞到队列里
  • threadFactory:线程共厂,用来创建线程用的,有提供默认的共厂,例如Executors.defaultThreadFactory()
  • handler:拒绝策略,当加入的线程超过的最大线程数时执行的一系列拒绝策略。

线程池流程用张图概括如下
在这里插入图片描述

在这里插入图片描述

源码如下,注释很详细

    public void execute(Runnable command) {
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            //首先判断当前线程数是否小于核心线程数?如果小于,则直接调用`addWorker`方法
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //workQueue.offer 向队列插入线程,返回boolean类型代表是否插入成功
        if (isRunning(c) && workQueue.offer(command)) {
            // 如果入队成功,我们仍然需要仔细检查是否应该添加一个线程
            //因为可能存在之前的线程死掉了,或者线程关闭了因此,
            // 我们重新检查状态,并在必要时回滚排队(如果已停止),或者在没有线程的情况下启动新线程。
            int recheck = ctl.get();
            if (!isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //往队列里插入失败,则再去尝试创建线程执行任务
        else if (!addWorker(command, false)) {
            //如果尝试创建线程执行任务失败则执行拒绝策略
            reject(command);
        }
    }

5.拒绝策略默认有哪几种??

  1. AbortPolicy:超出最大线程数就丢弃任务并抛出RejectedExecutionException异常,默认的处理方式。
  2. CallerRunsPolicy:用调用者所在线程来执行当前任务
  3. DiscardOldestPolicy:丢弃队列最前面的任务,并执行当前线程
  4. DiscardPolicy:直接丢弃加入来的任务,但是不抛出异常。

6.使用线程池有什么好处??

  • 可以有效防止重复创建&销毁线程带来的性能问题。
  • 可以统一管理线程
  • 提高响应速度,不需要等待创建线程

7.线程池数量如何设置??

  • IO密集型:CPU核心线程数*2
  • CPU密集型:CPU核心线程数+1
    获取CPU核心线程数的方法Runtime.getRuntime().availableProcessors(),这里指的是最大线程数

8.shutdown与shutdownNow的区别???

  • shutdown将状态至为SHUTDOWN;shutdownNow至为STOP
  • shutdown中断空闲的线程,正在执行的线程执行完,;shutdownNow中断所有线程
  • shutdown没有返回结果;shutdownNow返回没执行的任务列表

9.interrupt() interrupted() isInterrupted()三者的区别???`

  • interrupt:中断标志位,并不能真正的停止线程,需线程自行决定是否中断
  • interrupted:interrupted判断标志位是否中断,但是会讲标志位置为false
  • isInterrupted:判断标志位是否中断,如果调用了interrupt(),则isInterrupted返回true

10.如何安全的关闭一个线程???
接代码演示,

在这里插入图片描述
之前中断线程都是自己定义一个布尔变量 放到while(boolean)里,这种做法是不推荐的。原因是线程阻塞或者挂起的时候是不会判断自己定义的布尔变量的值

11.Thread的start()方法执行两次会发生什么???

抛出IllegalThreadStateException异常

    public synchronized void start() {
        if (started)
            throw new IllegalThreadStateException();
     }

12.yield方法了解吗???

  • 让出CPU的执行权,重新分配执行权,让出的线程还是有机会拿到CPU的执行权。
  • 只是让出执行权,不会释放锁

12.sleep wait yield对锁的影响???

sleep和yield不会释放锁,wait会释放锁,被唤醒时会重新拿到锁。

13.synchorized 关键字锁普通方法和静态方法的区别?什么是可见性??

  • 普通方法(也叫对象锁):锁的是当前这个类的实例
  • 静态方法(也叫类锁):锁的是当前类的class对象,一个JVM虚拟机里只有一个class对象
  • 什么是可见性:通俗来说可见性就是不同线程之间访问同一个变量,一个改了值另外一个线程是不知道的,最简单的操作就是给变量加上volatile关键字

14.sleep是可以被中断的吗??

可以,如果线程在sleep期被中断,则会抛出一个异常,可以查看问题10

15.ThreadLocal是什么??

ThreadLocal是Java里一种特殊的变量。ThreadLocal为每个线程都提供了变量的副本,使得每个线程在某一时间訪问到的并非同一个对象,这样就隔离了多个线程对数据的数据共享。
在内部实现上,每个线程内部都有一个ThreadLocalMap,用来保存每个线程所拥有的变量副本。

16.Executors ExecutorService的 Executor区别,为什么不推荐使用Executors??

  • Executors像是一个工具类,也可以理解为工厂吧,里面大部分方法都是static的,return对象是Executor的实现类
  • Executor也是接口,内部只有一个方法就是执行Runnable;void execute(Runnable command);
  • ExecutorService是个接口实现Executor,提供了其他方法,例如shutdown() shutdownNow()
    真正的线程池是实现ExecutorService的类 如图所示
    在这里插入图片描述

为什么不推荐使用Executors

可以理解为:是不推荐使用Executors默认的方法,比如

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

这里的maximumPoolSize传的无限大,这样肯定是不行的,我们应该按照自己的需求和业务来自定义我们的线程池,可以参考问题4来自定义参数,初始化我们的线程池

17.使用Okhttp的时候为什么不用自带的线程池(我简历写了okhttp的封装)??

可以说,默认的线程池不满足我们的需求,比如我们需求一次最多请求10个,最多同时支持3个,对应corePoolSize==3 maximumPoolSize==10,我们看看OkHttp默认的线程池是怎么样的呢?

在这里插入图片描述

18.双重校验锁单例模式为什么要判断两次空??

加入现在有个两个线程同时走到第一个锁那,此时单利对象为空,都进到了if语句里,此时CPU时间片轮转,第一个线程处于等待状态,第二个还在正常执行;过一会第一个线程拿到执行权,继续执行的时候如果不再次判断一次是否为空,那么就会创建两个对象,失去了单例的意义;

public class Singleton {
    private static volatile Singleton singleton = null;
    private Singleton() {
    }
    public static Singleton getInstance(){
        if(singleton==null){
           //假设两个线程同时执行到这,CPU调度,第一个线程让出执行权
            synchronized (Singleton.class){
                if(singleton==null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

内容概要:本文提出了一种基于瞬态三角哈里斯鹰算法(TTHHO)的多无人机协同集群在三维空间中的避障路径规划方法,旨在通过优化路径长度、飞行高度、威胁规避和转弯角度等关键因素,实现以最低综合成本为目标的全局路径规划。该方法结合智能优化算法与多智能体协同机制,在复杂三维环境中有效解决动态障碍物规避与飞行安全性问题,并通过Matlab平台进行算法编码实现与仿真实验,验证了其在路径最优性、收敛速度和避障能力方面的优越性能。研究涵盖了三维空间建模、目标函数构建、约束条件处理及多无人机协同策略设计,提升了无人机系统在实际应用场景中的自主导航与智能化决策水平。; 适合人群:具备一定编程基础,熟练掌握Matlab仿真环境,从事无人机路径规划、智能优化算法、多智能体协同控制等相关方向研究的科研人员、工程技术人员及研究生。; 使用场景及目标:① 实现多无人机在复杂三维环境下的协同避障路径规划,确保飞行安全与任务效率;② 研究基于哈里斯鹰算法及其改进版本(如TTHHO)的智能优化机制在路径规划中的应用;③ 推动多目标优化(路径最短、能耗最低、威胁最小、飞行平稳)下无人机自主导航系统的开发与落地; 阅读建议:此资源以Matlab代码实现为核心支撑,建议读者深入理解TTHHO算法原理的基础上,结合文中提供的仿真模型进行代码调试与参数调优,进一步探索不同环境设置和约束条件下算法的适应性与鲁棒性,鼓励通过扩展威胁模型或引入通信延迟等现实因素开展深化研究。
内容概要:本文档聚焦于“三相并网逆变器虚拟阻抗+统一有源阻尼策略SVPWM+SPWM调制仿真”这一核心技术主题,系统研究了在三相并网逆变系统中引入虚拟阻抗与统一有源阻尼的控制策略,旨在提升系统在弱电网条件下的稳定性、动态响应能力及并网电能质量。通过Simulink仿真平台,详细构建了包含SVPWM(空间矢量脉宽调制)与SPWM(正弦脉宽调制)两种主流调制方式的控制系统模型,深入对比分析了不同调制策略对系统性能的影响,并验证了所提出策略在抑制LC谐振、降低电流畸变、增强系统鲁棒性方面的有效性。文档还整合了大量电力电子与新能源领域的相关仿真研究案例,涵盖光伏逆变、储能控制、微电网调度、VSG控制等多个方向,展现出丰富的技术内涵和扎实的工程应用背景。; 适合人群:适用于具备电力电子技术、自动控制理论及新能源发电系统等相关专业知识背景的科研人员、电气工程类研究生以及从事并网逆变器、微电网控制、电力系统仿真等方向的工程技术人员。; 使用场景及目标:① 深入理解并掌握虚拟阻抗与统一有源阻尼技术在三相并网逆变器中的设计原理与实现方法;② 对比分析SVPWM与SPWM调制策略在系统稳定性、谐波抑制和动态性能上的差异;③ 基于Simulink平台进行逆变器并网控制算法的建模、仿真与验证,服务于高水平科研项目、学位论文撰写或实际工程项目开发。; 阅读建议:建议读者结合文档中提及的Simulink仿真模型及相关代码资源,亲自动手搭建和调试核心控制回路,重点关注虚拟阻抗的参数整定、电流内环与电压外环的协同控制结构、以及SVPWM/SPWM调制模块的具体实现细节,从而深化对系统稳定机理和高性能控制策略的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值