本文最后更新于 2024-11-21,文章内容可能已经过时。

39-创建线程池的方式以及作用

newCacheThreadPool:缓存可重复利用;

newFixedThreadPool:可重复固定线程数的线程池;

newSingleThreadExecutor:创建一个使用单个worker线程的线程池,以无界队列来运行;

newSingleThreadScheduledExecutor:创建一个单线程,可以在给定延迟后运行命令,或者定期执行;

newScheduledThreadPool:创建一个线程池,可以在给定延迟后运行命令,或者定期执行;

newWorkStealingPool:创建一个带并行级别的线程池。

40-字符串以及数字的反转

public class ReverseString {

public static void main(String[] args) {

String originalString = "Hello, World!";

String reversedString = new StringBuilder(originalString).reverse().toString();

System.out.println("Original String: " + originalString);

System.out.println("Reversed String: " + reversedString);

}

}

41-oss和fastdfs的区别

oss:高稳定性和高可靠性,但是相比于fastdfs在高并发场景存在瓶颈;维护成本高;适用于在不同地域配置数据中心。

fastdfs:是基于HTTP协议实现的,具有非常快的上传,下载,传输速度,能够处理数千并发请求;可自行搭建;适用于自行管理文件存储和访问,或者高并发文件存储和访问场景。

42-一直点击朋友圈喜欢怎么保证不出问题

可以加个时间间隔,或者设置一个token验证

43-nginx如何实现负载均衡

什么是负载均衡:负载均衡就是代理服务器将接受的请求均衡的分发到各个服务器中。

轮询,最少连接数,加权,ip哈希。

定义一组后端服务器,配置负载均衡算法,配置代理服务器,健康检查。

44-cookie和session的区别

cookie:存放在本地磁盘中;单个保存数据小于等于4kb,一个站点最大保存20个cookie;只能保管ASCII字符本地可见的存储在服务器;可设置长久有效;不占用服务器资源

session:存放在服务器对象;存储没上限;能存储任何数据;不可见;每次关闭窗口,session会实效。占用服务器资源。

45-springmvc注解的作用

@RequestMapping("/AAA")放在类上,是父接口(url/路径)

....(@RequestBody AAA bbb)将前端json转换为后端java对象(放在变量前)

@ResponseBody将后端java对象转换为json数据(放在类|方法上)

.....(.../{bbb}) .....(@PathVarible AAA aaa)从某个路径上获取参数

aaa@ControllerAdvice声明该类是一个全局异常处理类

@ExceptionHandler(aaa.class)用在异常处理类中的某个方法上,标记这个方法是用来处理哪种异常的。

46-rocketmq如何保证消息不丢失

消息生产者端:采取send()同步发送消息。设置发送失败后重试次数。采用集群部署。

broker端:修改刷盘策略为异步刷盘;集群部署。

消费者端:完全消费后进行手动ack确认。

47-tcp和udp的区别

TCP:面向连接,传输可靠,适用于少量数据传输;

UDP:面向非连接,不可靠,大量数据速度慢快。

48-事务的特性

ACID:原子性,一致性,隔离性和持久性。

A:不可被分割,要么全部执行,要么全部不执行;

C:一种正确状态转化为另一种正确状态;

I:在一个事务提交之前,不允许把该事务对数据的任何改变提供给其他事务;

D:事务提交后就永久保存在数据库中,即使在提交之后有了故障也不影响。

49-常见的异常

运行时异常和编译时异常。

运行时异常:程序逻辑错误引起,不处理也会编译通过(java编译器不检查)。空指针异常,类型强制转换异常,数组下标越界异常等。都是RuntimeException类及其子类。

编译时异常:除了RuntimeException的都是,必须处理,否则编译不通过。比如:IOException,SQLException以及自己定义的异常(一般不建议自定义)。都是Exception类及其子类。

50-重载和重写

重载:发生在同一个类中,方法名必须相同,参数列表必须不同,返回值和访问修饰符没有要求。发生在编译时。

重写:发生在父子类中,方法名和参数列表必须相同,返回值和异常范围小于等于父类,访问修饰符必须大于等于父类。

51-单例模式

单例模式:某个类的实例在多线程中只会被创建一次。

饿汉式:初始是初始化。安全

懒汉式:延迟初始化,不安全

......{

private static Singleton instance;

private intance(){}

private Singleton getInstance(){

if(instance ==null){

instance=new Singleton();

}

return instance;

}

}

双检索:延迟初始化,安全。

52-数据库的优化

定位执行效率慢的sql语句;

避免索引失效;

sql语句调优;

合理的数据库设计。

53-sql优化

根据业务建立复合索引只查询业务需要的字段;

多表连接的字段上可建立索引;

where条件上建立索引;

优化insert语句进行批量插入;

使用order by时不用select *,只需要查询需要排序的,尽量同时升降序;

分组是默认为降序,当不用可以进行order by null禁用;

尽量避免子查询。

54-数据库的死锁以及如何避免

死锁:

指两个或者多个事务在执行过程中,由于互相等待对方持有的资源,导致所有事务都无法继续执行。

解决:

按照同一顺序访问对象;

使用较低的隔离级别,比如读写未提交;

使用索引;

避免长事务,尽量缩短事务的执行时间;

优化查询语句,减少不必要的访问;

使用行锁;

使用乐观锁;

定期检查处理。

55-主键,外键的区别,索引的好坏

主键:每条数据的唯一标识,不可为空,唯一,不可重复,不可改变。primary key

外键:用于建立各个表之间的联系,一个外键关联另一个的主键。

索引的优点:

加快数据检索/查询速度,最主要的;

加速表和表之间的连接;

提高分组效率;

减少排序成本。

缺点:

占用空间;增加维护成本;不合理的索引设计会降低查询速度。

56-如何避免索引失效

模糊查询时,左边的列不能使用索引,否则右边也会失效;

索引上不可进行运算;

字符串索引不加引号会失效;

避免使用select *;

or 连接字左右同时有。

57-mysql单表上限,索引上限

mysql底层是B+数存储。

单表上限不建议超过2000万,索引一张表最多支持64个。

58-数据库两种引擎

MyISAM:mysql5.5所支持引擎,支持表锁,不支持事务。

InnoDB:5.5以后的引擎,支持行锁,支持事务。

59-介绍一下隔离级别解决什么事以及幻读是什么,怎么解决的

读取未提交:所有的事务都可以读取到其他事务未提交的数据。会产生脏读。

读取已提交:大多数数据库默认级别。解决脏读,只能看见已提交的事务。会产生不可重复读问题。

可重复读:mysql的默认级别。会产生幻读。幻读:当用户读取某一范围的数据行时,另一个事务又在该范围内插入新行,再读取时就会出现新行。通过多版本并发控制mvcc机制解决。

可串行化:强制事务排序,使之不可能互相冲突。

60-数据库的主从复制以及分库分表

主从复制:将主库的数据复制到其他从库中。优点:数据备份,读写分离,数据一致性,扩展性。

分库分表:将一个数据库|表,分解到多个库|表中。为了提高性能,保证数据安全,但也会导致事务性问题和表连接问题。

61-索引

分类:普通索引,唯一索引,主键索引,联合索引,全文索引。

62-&&和&的区别

&&:逻辑运算符,具有短路行为,左边为false,右边不进行运算

&:既是位运算符,也是逻辑运算符,不具有短路行为,左边不影响右边。

63-垃圾回收机制

分为两大部:如何发现垃圾,如何处理垃圾。

注意:线程私有的不存在gc,只有共享的堆才有gc。

如何发现垃圾:引用计数算法,根搜索算法

如何处理垃圾:标记-复制算法,标记-清楚算法,复制算法,分代收集算法

64-char和varchar的区别

char:长度固定;存储空间分配固定,如果存储字符小于定长,会造成空间浪费;最大长度为255字符;存储时会删除空格;处理数据时效性高。

varchar变长;只存储实例需要的字符加一个额外的字节;动态分布;65535;存储时保留空格;处理数据时效性低。

65-除了atowaird注入,还有哪种注入

@Atowaird:可以放在属性或者方法上,先根据类型注入,若存在多个属性相同的对象,会按照属性名注入;如果放在方法上,表示自动执行当前方法,如果有参数,会自动从ioc容器中寻找同类型的对象给参数传值。

@Resource:只能放在属性上,先按照属性名匹配ioc容器中对象,没成功根据当前属性类型匹配。也可以@Resource(name="对象id"),根据对象id注入。

66-素数

public class PrimeChecker {

public static void main(String[] args) {

int number = 29; // 你可以改变这个数来测试不同的值

if (isPrime(number)) {

System.out.println(number + " 是素数。");

} else {

System.out.println(number + " 不是素数。");

}

}

public static boolean isPrime(int num) {

// 小于等于1的数不是素数

if (num <= 1) {

return false;

}

// 检查从2到sqrt(num)的所有数是否能整除num

for (int i = 2; i <= Math.sqrt(num); i++) {

if (num % i == 0) {

return false; // 如果找到一个因子,则num不是素数

}

}

return true; // 没有找到因子,num是素数

}

}

sqrt指得是非负平方根。

67-反射

反射:在运行状态中,对于任意一个类能够知道这个类所有的属性和方法;并且对任意一个对象,都能够调用它的任意一个方法。

68-获取Class对象

调用某个对象的getClass方法:

AAA aaa=new AAA();

Class c1=aaa.getClass();

调用某个类的class属性:

Class c2=类C.class;

使用class类中的forname方法:

Class c3=Class.forname("类的全路径");(最常用)

69-如何用反射拿到类的所有public

先过去类的class对象,然后再通过调用class对象的getMethods()方法来获取类的所有public,包括所继承的方法。(一般用数组接受,最后遍历输出就行)

70-java是不是可跨平台的

71-int与integer比较

int:基本类型,默认值为0,存储在栈中,不需要实例化,==;

integer:引用类型,默认值null,堆中,必须实例化(new Integer/Integer.valueof),equlas。

二者之间可以自动拆装箱,自行转换。

72-int与integer==的比较

int a=10,Integer b=10,Integer c=new Integer(10),Integer d=Integer.valueof(10)

Integer f=10;

a==b,true,integer会自动拆箱

a==c,false

c==d,false,因为两个是对象是通过new比较。

b==c,false

b==f,true,在范围内为true,之外为false

73-介绍springapplication

@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan

配置类+自动导入+包扫描

74-reds中rdb是不是默认开启的,如何开启,宕机之后哪种恢复的快

是默认开启的,redis的配置文件为redis.conf

rdb快,但是aof更完整

75-new String("xyz")创建了几个对象

两个,一个放在堆中,一个放在常量池中。

76-final

修饰类:该类不可被继承

修饰方法:该方法不可被重写

修饰变量:变量不可被更改

77-反射的应用

获取Class对象,获取成员变量getFields(),获取构造方法getConstructors,获取所有public方法。

78-io流

分为输入输出流(Input/Output)。

字节流

字符流

输入流

字节输入流(InputStream),读取字节信息。FileInputStream是一个常用的字节输入流,可以直接指定文件路径,也可以读取单字节数据。 常见方法:read

(Reader)字符输入流 InputStreamReader是字节流转成字符流,FileReader继承了这个,可以直接操作字符文件。 常见方法:read

输出流

字节输出流(OutputStream),写入字节信息到目的地。 FileOutputStream是常见的字节输出流,可以直接指定文件路径,也可以直接输就单字节数据。 常见方法:write

(Writer)字符输出流。 OutputStreamWriter是字符流转换成字节流,FileWriter可以直接操作字符流。 常见方法:write

缓冲输入流

字节缓冲输入流BufferedInputStream

字符缓冲输入流BufferedReader

缓冲输出流

字节输出流BufferedOutputStream

字符缓冲输出流BufferedWriter

随机访问流

RandomAccessFile,支持随意跳转到文件的任意位置进行读写,支持断点续传。

缓冲流作用:

降低io操作所消耗性能,缓冲流将数据加载到缓冲区,一次性读取或者写入多个字节,从而避免频繁的io操作,提高流的输就效率。

注意:

常用的sout底层就是print调用的是PrintStream的write方法,字节输出流。

音视频文件,图片一般采用字节流形式。

79-zookeeper应用场景

统一命名服务,统一配置管理,统一集群管理,集群选主,分布式锁。

80-布尔默认值

false

81-map有几个线程安全的

hashtable和ConcurrentHashMap

82-快速排序

public class QuickSort {

// 主方法,用于测试

public static void main(String[] args) {

int[] array = {10, 7, 8, 9, 1, 5};

int n = array.length;

QuickSort ob = new QuickSort();

ob.quickSort(array, 0, n - 1);

System.out.println("排序后的数组:");

printArray(array);

}

// 快速排序方法

void quickSort(int[] array, int low, int high) {

if (low < high) {

// pi 是分区索引,array[pi] 已经在正确位置

int pi = partition(array, low, high);

// 分别对左右子数组进行快速排序

quickSort(array, low, pi - 1);

quickSort(array, pi + 1, high);

}

}

// 分区方法

int partition(int[] array, int low, int high) {

int pivot = array[high]; // 选择最右边的元素作为基准

int i = (low - 1); // i 是较小元素的索引

for (int j = low; j < high; j++) {

// 如果当前元素小于或等于基准

if (array[j] <= pivot) {

i++;

// 交换 array[i] 和 array[j]

int temp = array[i];

array[i] = array[j];

array[j] = temp;

}

}

83-手撕代码:翻转队列

import java.util.LinkedList;

import java.util.Queue;

import java.util.Stack;

public class ReverseQueue {

public static void main(String[] args) {

// 创建一个队列并添加一些元素

Queue<Integer> queue = new LinkedList<>();

queue.add(1);

queue.add(2);

queue.add(3);

queue.add(4);

queue.add(5);

System.out.println("Original Queue: " + queue);

// 调用反转队列的方法

Queue<Integer> reversedQueue = reverseQueue(queue);

System.out.println("Reversed Queue: " + reversedQueue);

}

public static Queue<Integer> reverseQueue(Queue<Integer> queue) {

// 创建一个栈来辅助反转

Stack<Integer> stack = new Stack<>();

// 将队列中的所有元素压入栈中

while (!queue.isEmpty()) {

stack.push(queue.poll());

}

// 创建一个新的队列来存储反转后的元素

Queue<Integer> reversedQueue = new LinkedList<>();

// 将栈中的所有元素依次弹出并添加到新队列中

while (!stack.isEmpty()) {

reversedQueue.add(stack.pop());

}

return reversedQueue;

}

}

// 交换 array[i + 1] 和 array[high] (或基准)

int temp = array[i + 1];

array[i + 1] = array[high];

array[high] = temp;

return i + 1;

}

// 打印数组的方法

static void printArray(int[] array) {

int n = array.length;

for (int i = 0; i < n; ++i)

System.out.print(array[i] + " ");

System.out.println();

}

}