【面试系列】八股文之线程篇202306

news2024/11/25 8:11:55

union all和union的区别

union all:包含重复行

union:不包含重复行

线程池的shutdown()与shutdownNow()方法的区别

shutdown(),调用shutdown方法,线程池会拒绝接收新的任务,处理中的任务和阻塞队列中的任务会继续处理。

public class ThreadPoolTest {

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 2,
                1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2));
        Runnable runnable = () -> {
            System.out.println(Thread.currentThread().getName() + "before ~~~");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "after ~~~");
        };
        pool.execute(new Thread(runnable));
        pool.execute(new Thread(runnable));
        pool.execute(new Thread(runnable));

        pool.shutdown();
        System.out.println("活跃线程数:" + pool.getActiveCount() + ",队列任务数:" + pool.getQueue().size());
//        pool.execute(new Thread(runnable));
    }
}

shutdownNow(),会给workers中所有的线程发送interrupt信号,将延迟队列的任务移除并返回。

原理分析

执行任务,尝试添加线程。

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        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);
    }

ThreadPoolExecutor#addWorker,当判断当前线程池的状态已经是SHUTDOWN,返回false,执行拒绝策略。

    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
        // ...
    }

ThreadPoolExecutor#shutdown

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

ThreadPoolExecutor#advanceRunState,修改状态为SHUTDOWN

    private void advanceRunState(int targetState) {
        for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

ThreadPoolExecutor#interruptIdleWorkers(),对于空闲线程,执行interrupt方法。

private void interruptIdleWorkers() {
    interruptIdleWorkers(false);
}

    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

ThreadPoolExecutor#shutdownNow,修改任务状态为STOP

    public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(STOP);
            interruptWorkers();
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

ThreadPoolExecutor#interruptWorkers,发送中断信号。

    private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers)
                w.interruptIfStarted();
        } finally {
            mainLock.unlock();
        }
    }

ThreadPoolExecutor#drainQueue,将延迟队列中的任务数据移动到任务list中。

    private List<Runnable> drainQueue() {
        BlockingQueue<Runnable> q = workQueue;
        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
        q.drainTo(taskList);
        if (!q.isEmpty()) {
            for (Runnable r : q.toArray(new Runnable[0])) {
                if (q.remove(r))
                    taskList.add(r);
            }
        }
        return taskList;
    }

spring中 initMethod,@PostConstruct,InitializingBean 初始化的顺序

https://juejin.cn/post/7006965516891848741

@PostConstruct > InitializingBean > initMethod

PostConstruct是实例初始化的时候调用的。

  • 实例初始化会调用aware方法,BeanNameAwareBeanClassLoaderAwareBeanFactoryAware

  • 调用BeanPostProcessor的前置方法

  • 执行InitializingBeanafterPropertiesSet方法。如果有init方法,执行init方法。

  • 调用BeanPostProcessor的后置方法

@PostConstruct 的具体执行的后置处理器是InitDestroyAnnotationBeanPostProcessor

InitializingBean 的执行处理在后置处理器的前置方法执行完后。

initMethod初始化方法在InitializingBean后执行的

Spring 配置中的 classpath:classpath*: 的区别

classpath:,加载一个指定location的资源文件。

classpath*:,会加载所有指定location的资源文件。

守护线程是什么?守护线程和非守护线程的区别是?守护线程的作用是?

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                System.out.println(System.currentTimeMillis());
            }
        });
//        t1.setDaemon(true);
        t1.start();
        Thread.sleep(2000);
    }

用户线程就是非守护线程,默认创建的线程就是用户线程。当主线线程停止,用户线程也会停下来。如果是用户线程,则会一直运行。

Java里一个线程调用了Thread.interrupt()到底意味着什么?

  • 如果当前线程处在阻塞状态(例如sleep,join,wait),会退出阻塞状态,抛出InterruptedException异常。
  • 如果正常活动,修改中断标志位为true
public class InterruptTest {

    public static void main(String[] args) throws InterruptedException {
//        t1();
        t2();

    }

    private static void t2() throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        TimeUnit.MILLISECONDS.sleep(10);

        thread.interrupt();
    }

    private static void t1() throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("开始搬砖!");
            //只要代码里没有异常,那么我们可以通过判断线程是否中断来执行业务操作
            //当其他线程发出线程中断信号后就会跳出正在执行的任务,往下执行使线程结束运行。
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("西西弗斯的陷阱:无脑循环,日复一日搬砖!");
            }
            System.out.println("神迹出现,结束搬砖!");
            System.out.println(Thread.currentThread().isInterrupted());//true
            System.out.println(Thread.currentThread().isInterrupted());//true
            System.out.println(Thread.interrupted());//true
            System.out.println(Thread.interrupted());//true
        });
        thread.start();
        TimeUnit.MILLISECONDS.sleep(10);
        System.out.println("启动超级进化形态!");
        thread.interrupt();
    }
}

Thread的静态函数interrupted与Thread的对象函数isInterrupted比较

  • 静态方法Thread.interrupted()会在检测线程中断状态标志是否为true后,还会将中断状态标志重置为false

  • 对象方法thread.isInterrupted()只是检测线程中断状态标志

sleep和wait有什么区别?

  • wait方法必须在synchronized方法块中,sleep可以单独使用。
  • wait方法是Object中的,sleep方法是Thread中的。
  • 唤醒方式不同。sleep自动唤醒,wait是需要别的线程notify唤醒的。
  • sleep在休眠时不释放锁,wait在休眠时会释放锁。
  • 调用sleep方法会进入到TIMED_WAITING,而调用wait方法会进入到WAITING

线程的五种状态

  • 新建。new Thread()
  • 运行。执行start方法之后
  • 无限等待。Object.wait()
  • 有限等待。Object.wait(timeout)或者Thread.sleep(timeout)
  • 阻塞。阻塞是在等待排他锁,synchronized
  • 结束,terminated

Thread.join()方法

Thread.join()会造成主线程阻塞。当线程执行结束之后,会唤醒主线程。

public class ThreadJoinTest {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
//           while (true){
            System.out.println("t1 run");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//           }
        });
        Thread t2 = new Thread(() -> {
            System.out.println("t2 run");
        });
        Thread t3 = new Thread(() -> {
            System.out.println("t3 run");
        });
        t1.start();
        t1.join();
        t2.start();
        t2.join();
        t3.start();
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/718761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis基础及哨兵集群部署、故障切换

一、概述 Redis是一个开源的&#xff0c;使用C语言编写&#xff0c;支持网络&#xff0c;可基于内存工作亦可持久化&#xff08;AOF、RDB&#xff09;的日志型&#xff0c;key-values&#xff08;键值对&#xff09;数据库&#xff0c;一个速度极快的非关系型数据库&#x…

R语言APSIM模型及批量模拟

随着数字农业和智慧农业的发展&#xff0c;基于过程的农业生产系统模型在模拟作物对气候变化的响应与适应、农田管理优化、作物品种和株型筛选、农田固碳和温室气体排放等领域扮演着越来越重要的作用。 APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物…

Python 数据类型转换

文章目录 每日一句正能量前言隐式类型转换实例实例 显式类型转换实例实例实例实例 每日一句正能量 在人生的道路上&#xff0c;即使一切都失去了&#xff0c;只要一息尚存&#xff0c;你就没有丝毫理由绝望。因为失去的一切&#xff0c;又可能在新的层次上复得。 前言 有时候&…

HOT41-二叉树的层序遍历

leetcode原题链接&#xff1a;二叉树的层序遍历 题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&…

redis如何实现持久化

RDB快照 RDB是一种快照存储持久化方式&#xff0c;具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中&#xff0c;默认保存的文件名为dump.rdb&#xff0c;而在Redis服务器启动时&#xff0c;会重新加载dump.rdb文件的数据到内存当中恢复数据。 开启RDB持久化方式 开启…

Vue生态及实践 - Vue Router(2)

目录 导航守卫 解析流程 代码演示 router.js pages/Foo.vue router/router.js router/history/base.js router/util/async.js router/components/RouterView.vue 接上一篇文章~&#xff0c;代码部分会有部分重叠&#xff0c;想看完整版的代码&#xff0c;看这篇文章的…

END-TO-END OPTIMIZED IMAGE COMPRESSION论文阅读

END-TO-END OPTIMIZED IMAGE COMPRESSION 文章目录 END-TO-END OPTIMIZED IMAGE COMPRESSION单词重要不重要 摘要&#xff1a; 单词 重要 image compression 图像压缩 quantizer 量化器 rate–distortion performance率失真性能 不重要 a variant of 什么什么的一个变体 …

大数据之flink容错机制

大数据之flink容错机制https://blog.51cto.com/dashujutongmeng/5241407

Spring Batch 批处理框架

一、SpringBatch 介绍 Spring Batch 是一个轻量级、全面的批处理框架&#xff0c;旨在支持开发对企业系统的日常操作至关重要的健壮的批处理应用程序。Spring Batch 建立在人们期望的 Spring Framework 特性&#xff08;生产力、基于 POJO 的开发方法和一般易用性&#xff09;…

从零开始 Spring Boot 60:一个实体映射到多个表

从零开始 Spring Boot 60&#xff1a;一个实体映射到多个表 图源&#xff1a;简书 (jianshu.com) 在之前的文章中我们讨论了 JPA 中的一对一关系&#xff0c;实际上存在一种特殊的一对一关系&#xff0c;即将一个实体映射到多张表&#xff0c;本文会讨论这种关系。 我之前提过…

elementui实现表格自定义排序

需求说明&#xff1a; 1、第一行不参与排序 2、实现带%排序 3、实现null值排序 4、实现值相等不排序 5、实现含有占位符‘–‘排序放到最后 效果图如下&#xff1a; <template> <div><template><el-table border :data"previewTableData" style…

ROS学习之从yaml文件中读取多传感器坐标系之间的静态TF关系并发布Topic

文章目录 0 引言1 工作空间创建并初始化2 创建ROS程序包3 创建yaml读取函数3.1 yaml文件3.2 读取函数 4 创建静态TF关系的发布主函数5 创建launch文件6 编辑CMakeLists.txt7 编译运行7.1 编译7.2 运行 0 引言 机器人中经常使用多种传感器来做定位和建图&#xff0c;而多个传感…

找出一个List中每个元素出现的次数

文章目录 一、需求&#xff1a;找出一个list中&#xff0c;每个元素出现的次数1. 普通实现&#xff08;hashmap&#xff09;&#xff1a;1.1 代码实现&#xff1a;1.2运行结果&#xff1a;1.3 案例分析&#xff1a; 2. 普通实现&#xff08;HashSet#Collections.frequency&…

Flask学习笔记(2)应用部署

本文将介绍如何部署Flask应用。   部署Flask应用&#xff0c;主要是要运用多线程与多进程&#xff0c;提高接口的并发能力。我们以下面的Python代码&#xff08;server.py&#xff09;为例进行演示&#xff1a; # -*- coding: utf-8 -*- import time import datetime from f…

04-HAL库UART配置及协议解析设计

本节内容介绍 1、HAL库UART 在cubemx中的配置及注意事项;2、HAL库UART详解与结构介绍;3、实现简单地UART数据收发&#xff1b; 源码地址&#xff1a; HAL库UART在cubemx中的配置 串口原理图 串口1咱们已经用作rtt的print使用了&#xff0c;所以使用另外一组串口来进行串口…

android studio 4.0以上隐藏调用方法参数名提示

引入&#xff1a; android studio在编辑代码的时候&#xff0c;调用函数时会接口处会自动提示参数名&#xff0c;方便代码书写时对传参命名的规范性。 可以如果代码是魂效过的&#xff0c;那会适得其反&#xff0c;l,l1,l2,i,i1,i2这样的参数名提醒反而会混淆视听。 这时候可…

图书馆机器人的应用,科技助力新趋势

随着科技的发展和智能化时代的到来&#xff0c;图书馆越来越多地引入了机器人作为服务和管理的工具。图书馆机器人可以轻松地完成多种任务&#xff0c;包括为用户提供导航服务、管理借还书、整理图书、清扫图书馆等。 首先&#xff0c;图书馆机器人可以为用户提供导航服务。在庞…

讲讲仿真软件的文件导入

仿真软件识别导入的设计文档是有区别的&#xff0c;实际的使用经历&#xff0c;ADS只是用于搭建Channel通道仿真&#xff0c;那本文以Cadence的Sigrity和Ansys的SIwave为例&#xff0c;讲讲仿真软件的文件导入。 先以Sigrity为例&#xff0c;打开软件&#xff0c;File 菜单Open…

记一次 JVM 参数调整导致 ShardingSphere-Proxy 性能下降的问题排查过程

问题现象 在性能测试中&#xff0c;分别对两个版本差异间隔一天的 ShardingSphere-Proxy 做性能测试&#xff0c;发现版本更新的 Proxy 比旧的 Proxy 在 TPC-C 场景下峰值 tpmC 下降了 7% 左右。 排查过程 在性能测试期间&#xff0c;使用 async-profiler 分别对两个进程进行…

根据aop实现自定义缓存注解

根据aop实现自定义缓存注解 自定义注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.concurrent.TimeUnit;/*** author: yanche…