java面经

news2024/11/26 20:35:06

String, StringBuffer, StringBuilder区别

第一点是可变性。String不可变,String Buffer和StringBuider可变。这是因为String被final修饰,每次操作都生成新的对象。StringBuffer和StringBuilder的父类AbstractStringBuilder没有被final修饰。

第二点是线程安全。String和StringBuffer是线程安全的,因为String被final修饰,StringBuffer所有的方法都用了synchronized。StringBuilder是线程不安全的。因此单线程时使用StringBuilder,性能较好,多线程时使用StringBuffer,线程安全。

为什么静态方法不能调用非静态方法和变量?

静态方法是属于类,在类加载时就会分配内存,可以通过类名去直接访问。

非静态成员属于类的对象,只有该对象实例化之后才存在,通过类的对象去访问。

异常类型

Throwable下面有两个直接子类,Error和Exception。

Error是严重的系统错误,无法被应用程序捕获和处理,例如内存溢出或者堆栈溢出。

Exception的子类有RuntimeException和其他Exception。

RuntimeException通常不需要在方法的声明中显式地捕获或声明抛出,例如空指针异常,算数异常等等。

其他Exception也称Checked Exception,这些异常通常需要在方法的声明中显式地捕获或声明抛出,例如IOException,SQLException等等。

捕获:  try...catch,一般用在调用处,能让代码继续往下运行。

抛出: throw throws,在方法中,出现异常了,方法就没有继续运行下去的意义了,采取抛出处理让该方法结束运行并告诉调用者出现了问题。

字节流与字符流区别?

适用场景:字符流适合文本文件,字节流适合图片视频音频。因为字符流能自动处理文件编码,确保正确解析文件中的字符,并且字符流读取非文本文件时,可能会将某些特定的字节序列视为文件的结尾,导致数据丢失。

缓冲:字节流不使用缓冲,字符流将频繁访问的资源放入内存。

字节流是InputStream、OutputStream。字符流是Reader、Writer。

ArrayList扩容机制

ArrayList每次扩容是原来的1.5倍。因为扩容时,会将老数组中的元素重新拷贝一份到新的数组中,因此扩容代价比较高,我们要尽量避免数组扩容,尽可能地在创建ArrayList对象时指定其容量。

是否线程安全?如何线程安全地操作ArrayList?

ArrayList线程安全的操作方法

  • Vector。List list = new ArrayList(),替换为List arrayList = new Vector<>()。使用了synchronized关键字,效率较低。

  • JUC中的CopyOnWriteArrayList。CopyOnWriteArrayList<String> list =new CopyOnWriteArrayList<String>() 。写数据时将原来array复制到新的array,修改后,将引用指向新数组,任何可变的操作(add、set、remove等)都通过ReentrantLock 控制并发,读数据时不用加锁,适用于读多写少的并发场景。

  • Collections.synchronizedList(list)。方法都加了synchronized修饰。加锁的对象是当前SynchronizedCollection实例,适用于将现有的非线程安全的 List 转换为线程安全的情况。

LinkedList线程安全的操作方法

JUC中的ConcurrentLinkedQueue和Collections.synchronizedList(List)。

HashMap、TreeMap、LinkedHashMap的区别?

相同点

  • 都属于Map;
    • Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许值重复。
  • 都是线程不安全的

不同点

 

SingleDateFormat--线程安全的操作方法(有实例)

 SingleDateFormat线程不安全的原因

SingleDateFormat类内部有个Calendar对象引用,Calendar用于存储日期信息,如果SimpleDateFormat是多个线程之间共享的, 那么多个线程可以同时访问和修改Calendar对象的状态。就会出现线程安全问题。

解决方案

1、每调用一次方法就会创建一个SimpleDateFormat对象,但每调用一次方法就会创建一个SimpleDateFormat对象。

2、方法加synchronized,不过性能差。

3、使用ThreadLocal,这种方式推荐。

4、如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter(所有字段都是final类型)代替Simpledateformatter。

线程池有哪些参数?

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

1、corePoolSize
线程池的核心线程数
即便是线程池里没有任何任务,也会有corePoolSize个线程在候着等任务。

2、maximumPoolSize
最大线程数。
超过此数量,会触发拒绝策略。

3、keepAliveTime
线程的存活时间。
当线程池里的线程数大于corePoolSize时,如果等了keepAliveTime时长还没有任务可执行,则线程退出。

4、unit
指定keepAliveTime的单位
比如:秒:TimeUnit.SECONDS。

5、workQueue
一个阻塞队列,提交的任务将会被放到这个队列里。

6、threadFactory
线程工厂,用来创建线程
主要是为了给线程起名字,默认工厂的线程名字:pool-1-thread-3。

7、handler
拒绝策略
当线程池里线程被耗尽,且队列也满了的时候会调用。
默认拒绝策略为AbortPolicy。即:不执行此任务,而且抛出一个运行时异常
 

线程池使用步骤?

1:创建一个线程池对象,控制要创建几个线程对象。

2:实现线程,新建一个类实现Runnable或者Callable接口。

3:使用submit或者execute提交线程调用。submit有返回值,返回值是future对象,可以获取执行结果。execute无返回值。

4:使用shutdown方法关闭线程池。

线程池的工作流程

CPU密集与IO密集的场景如何设置线程池参数?

如果任务被阻塞的时间少于执行时间,即这些任务是计算密集型的,则程序所需线程数将随之减少,但最少也不应低于处理器的核心数。核心线程数 = CPU核数 + 1

如果任务被阻塞的时间大于执行时间,即该任务是IO密集型的,我们就需要创建比处理器核心数大几倍数量的线程。例如,如果任务有50%的时间处于阻塞状态,则程序所需线程数为处理器可用核心数的两倍。核心线程数 = CPU核数 * 2 + 1

线程池的阻塞队列(BlockingQueue)

ArrayBlockingQueue

基于数组的FIFO队列;有界;创建时必须指定大小;入队和出队共用一个可重入锁。默认使用非公平锁。

LinkedBlockingQueue

默认大小的LinkedBlockingQueue将导致所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程不会超过 corePoolSize。(因此,maximumPoolSize 的值也就无效了)。使用无界队列的好处是可以避免任务因为队列满而被拒绝或阻塞,因此当每个任务相互独立且任务数量较大时,适合使用无界队列。

常见线程池种类

FixedThreadPool(固定线程池)

固定线程池是一种固定大小的线程池,其中线程数量是预先指定的。当有新任务提交时,如果线程池中有空闲线程,则立即执行;如果线程池中没有空闲线程,则任务进入等待队列,直到有线程可用。固定线程池适用于需要限制并发线程数量的场景,如服务器请求处理、并发任务数量可预知的情况。

SingleThreadExecutor(单线程池)

单线程池是只有一个工作线程的线程池,所有任务按照顺序执行,每个任务都在前一个任务执行完成后开始执行。适用于需要按照顺序串行执行任务的场景,如消息队列的消费者、数据库事务处理等。

ScheduledThreadPool(定时线程池)

定时线程池用于执行延迟任务或定时任务,可以指定任务的延迟时间或固定的执行间隔。定时线程池会根据任务的执行时间自动调度线程,保证任务按照预定的时间顺序执行。适用于需要定时执行任务的场景,如定时任务调度、定时数据备份等。

CachedThreadPool(缓存线程池)

缓存线程池根据需要创建线程,如果有空闲线程,则复用空闲线程执行任务;如果没有空闲线程,则创建新线程。当线程空闲时间超过指定的时间(例如60秒),则被终止并从线程池中移除。缓存线程池适用于任务数量不确定、任务执行时间短暂、需要快速响应的场景。

进程的三种创建方式

1、继承Thread类的方式进行实现:

定义一个MyThread继承Thread类

在MyThread类中重写run()方法

创建MyThread类对象

启动线程

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("MyThread线程方法执行" + i);
        }
    }
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

问题.run()方法和start()的区别

run():封装线程执行的代码,直接调用,相当于普通方法的调用,并没有开启线程

start():启动线程;然后由JVM调用此线程的run()方法

2、方式2:实现Runnable接口

定义一个类MyRunnable实现Runnable接口

在MyRunnable类中重写run()方法

创建MyRunnable类的对象

创建Thread类的对象,把MyRunnable对象作为构造方法的参数

启动线程

public class MyRunnable implements Runnable{
    @Override
    public void run() {
for (int i=0;i<10;i++){
    System.out.println("线程方法执行"+i);
}
    }
    public static void main(String[] args) {
        //创建了一个参数对象
        MyRunnable myRunnable = new MyRunnable();
        //创建了一个线程对象,并把参数传递给这个线程
        //在线程启动后,执行的就是参数里面的run方法
        Thread thread = new Thread(myRunnable);
        //run方法
        thread.start();
    }
}

3、方式3:Callble和Future(可以获取返回结果)

定义一个类MyCallable实现Callable接口

在MyCallable类中重写call()方法

创建MyCallable类的对象

创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数

创建Thread类的对象,把FutureTask对象作为构造方法的参数

启动线程

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
for (int i=0;i<100;i++){
    System.out.println("MyCallable运行次数"+i);
}
        //返回值就是表示线程运行之后的结果
        return "你好";
    }
 
    public static void main(String[] args) {
        //线程开启之后需要执行里面的call方法
        MyCallable myCallable = new MyCallable();
        //可以获取线程执行完毕之后的结果,也可以作为参数传递给Thread对象
        FutureTask<String> futureTask = new FutureTask<String>(myCallable);
        //创建线程对象
        Thread thread = new Thread(futureTask);
        //开启线程
        thread.start();
 
        try {
            //获取返回结果
            String s = futureTask.get();
            System.out.println(s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
 
    }
}

调用get方法,就可以获取线程结束之后的结果,必须在线程结束之后才能获取否则只能死等线程

ReentrantLock和synchronized锁

ReentrantLock

 对象实例、类信息、常量、静态变量分别在运行时数据区的哪个位置?

各区域的数据

以JDK8为例:

  • 堆:对象实例、String常量池、基本类型常量池
  • 方法区:类信息、静态变量
  • 虚拟机栈:临时变量(方法内的变量)
  • 元空间:类常量池、运行时常量池

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

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

相关文章

MATLAB 之 非线性方程数值求解、最优化问题求解和常微分方程初值问题的数值求解

这里写目录标题 一、非线性方程数值求解1. 单变量非线性方程求解2. 非线性方程组的求解 二、最优化问题求解1. 无约束最优化问题求解2. 有约束最优化问题求解3. 线性规划问题求解 三、常微分方程初值问题的数值求解1. 龙格—库塔法简介2. 龙格—库塔法的实现 一、非线性方程数值…

Day975.如何使用JWT结构化令牌 -OAuth 2.0

如何使用JWT结构化令牌 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于如何使用JWT结构化令牌的内容。 OAuth 2.0 规范并没有约束访问令牌内容的生成规则&#xff0c;只要符合唯一性、不连续性、不可猜性就够了。这就意味着&#xff0c;可以灵活选择令牌的形式&…

将递归函数转成非递归函数的通用方法

看到过一道非常不错的面试题&#xff1a;不支持递归的程序语言如何实现递归程序&#xff1f; 之所以说这道题好&#xff0c;是因为&#xff1a; 首先&#xff0c;它不是纯粹考概念和死记硬背&#xff0c;求职者在回答问题之前需要进行一定的思考&#xff1b; 其次&#xff0c…

vim粘贴出现多余的#

vim粘贴yaml格式时&#xff0c;出现多余的#&#xff0c;格式错误 解决&#xff1a;设置paste :set paste 然后再粘贴即可

final不可变性

一、什么是不可变性&#xff08;Immutable&#xff09; 如果对象在被创建后&#xff0c;状态就不能被修改&#xff0c;那么它就是不可变的这个对象不能被修改指&#xff1a; 对象指向(引用)不可变字段不可变成员变量不可变 案列演示&#xff1a; person对象&#xff0c;age和…

我的C++学习笔记

声明&#xff1a; 写本篇博客的目的是为了整理自己在找工作时学习的C相关知识点&#xff0c;博客整体内容会分为两种风格&#xff0c;第一章基础部分是以常见C面试问题解答的形式呈现&#xff1b;其余部分是知识点层层递进的方式展现&#xff0c;比较系统。其中&#xff0c;在第…

Avalon 学习系列(三)—— 数据和指令同步

Avalon 有很多个指令&#xff0c;通过这些指令可以对 DOM 进行一些事件操作、或者样式修改。 ms-duplex Avalon 实现数据与视图的同步的方式是用 ms-duplex 将元素跟数据绑定在一起&#xff0c;如果有其中一个的值改变另一个值也将改变。 ms-duplex 是 avalon 的双向绑定属性…

OpenCV(C++)创建图片绘制图形(矩形、圆、文字、线段等等)

一、OpenCV介绍 OpenCV 是基于开源许可证的跨平台计算机视觉库,提供了一组丰富、广泛的图像处理和计算机视觉算法。OpenCV 支持多种编程语言,包括 C++、Python、Java 等,可以运行在 Linux、Windows、Mac OS 等平台上。 OpenCV 能够在图像上绘制各种几何形状、文本和曲线,…

学习ESP32笔记

学习ESP32笔记 1.platform IO插件的下载&#xff08;提前安装好python&#xff0c;不然在中间的一部分会一直报错&#xff09; VS Code下载platform IO时&#xff0c;开加速器&#xff08;VPN&#xff09;&#xff0c;并且关闭防火墙 这一步比较慢&#xff0c;大概等十来分钟…

Kendo UI for jQuery---02.开始---01.使用 Kendo UI for jQuery 的第一步

使用 Kendo UI for jQuery 的第一步 欢迎来到 Kendo UI for jQuery 入门的第一步指南&#xff01; 本指南演示如何通过添加所需资源和初始化 Kendo UI 网格来开始使用套件。 该过程借鉴了以下里程碑&#xff1a; 1.下载控件 2.添加所需的 JavaScript 和 CSS 文件 3.将网格绑…

如何使用postman做接口测试

常用的接口测试工具主要有以下几种&#xff1a; Postman: 简单方便的接口调试工具&#xff0c;便于分享和协作。具有接口调试&#xff0c;接口集管理&#xff0c;环境配置&#xff0c;参数化&#xff0c;断言&#xff0c;批量执行&#xff0c;录制接口&#xff0c;Mock Server…

【每日挠头算法题(6)】二叉树的所有路径|神奇字符串

欢迎~ 一、二叉树的所有路径思路&#xff1a;深度优先搜索具体代码如下&#xff1a; 二、神奇字符串思路&#xff1a;模拟双指针具体代码如下&#xff1a; 总结 一、二叉树的所有路径 点我直达~ 思路&#xff1a;深度优先搜索 使用深度优先搜索&#xff1a;即二叉树的前序遍历…

设计模式(十二):结构型之享元模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二、三)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(四)&#xff1a;创建型之原型模式 设计模式(五)&#xff1a;创建型之建造者模式 设计模式(六)&#xff1a;结构型之代理模式 设计模式…

编码生成矩阵与检错监督矩阵

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;https://github.com/timerring/information-theory 】或者公众号【AIShareLab】回复 信息论 获取。 文章目录 线性分组码基本概念…

Elasticsearch快速入门及使用

Elasticsearch快速入门及使用 一.Elasticsearch是什么二.基本概念1.index (索引)2. type (类型)3.Document (文档) 三.为什么Elasticsearch可以从海量数据里快速检索出数据四.Elasticsearch安装1.解压2.运行3.显示以下内容就是启动成功14.Kibana可视化软件安装 五.入门(基本的操…

如何编写有效的接口测试?

在所有的开发测试中&#xff0c;接口测试是必不可少的一项。有效且覆盖完整的接口测试&#xff0c;不仅能保障新功能的开发质量&#xff0c;还能让开发在修改功能逻辑的时候有回归的能力&#xff0c;同时也是能优雅地进行重构的前提。编写接口测试要遵守哪些原则&#xff1f;测…

unity Ignis - Interactive Fire(完美模拟:森林火灾、草原火灾、建筑火灾)

Ignis 可以把任何物体、植被或带皮带骨的网状物转换为可燃物体&#xff0c;它就会自动着火。然后&#xff0c;火焰可以蔓延&#xff0c;点燃其他物体&#xff0c;被粒子或光线熄灭&#xff0c;或者自然烧尽。也可以被粒子点燃。还会收到风力影响WindZone。 WindZone文档&#…

轻量级性能测试工具 wrk 如何使用?

项目设计之初或者是项目快要结束的时候&#xff0c;大佬就会问我们&#xff0c;这个服务性能测试的结果是什么&#xff0c;QPS 可以达到多少&#xff0c;RPS 又能达到多少&#xff1f;接口性能可以满足未来生产环境的实际情况吗&#xff1f;有没有自己测试过自己接口的吞吐量&a…

磁盘详解(一文搞懂磁盘)

目录 一.磁盘的结构 二.磁盘的分类 2.1按照磁头是否可以移动分类 2.2按照盘片是否可以更换分类 三.磁盘的读写过程 四.磁盘的调度 4.1FCFS先来先服务算法 4.2SSTF最短寻找时间优先 4.3 SACN扫描算法 4.4C-SACN循环扫描算法 4.5 SPTF&#xff08;最短定位时间优先&…

Maxwell安装使用

​欢迎光临我的博客查看最新文章: https://river106.cn 1、Maxwell简介 Maxwell 是由美国Zendesk开源&#xff0c;用Java编写的MySQL实时抓取软件。读取 MySQL binlogs 并将修改行字段的更新写入 Kafka, Kinesis, RabbitMQ, Google Cloud Pub/Sub 或 Redis (Pub/Sub or LPUSH)…