【Java 高频面试闯关秘籍】大梦谁先觉,平生我自知

一、mysql使用innodb引擎,请简述mysql索引的最左前缀如何优化orderby语句?

关键点:

(1)如果排序字段不在索引列上,filesort有两种算法:mysql就要启动双路排序和单路排序
(2)无过滤不索引
(3)order by 非最左filesort
(4)顺序错 filesort
(5)方向反 filesort

答案:

1)首先要对SQL进行分析检查必要的的查询字段、过滤字段、排序字段是否按顺序创建好了索引;
(2)如果查询字段不再索引中,可能会产生回表操作导致filesort降低性能;
(3)一定要过滤字段不然不能使用索引;
(4)排序字段和索引顺序不一致会导致filesort降低性能;
(5)多个字段排序时如果方向不一致也会导致filesort,降低性能;
(6)使用explain观察查询类型和索引利用情况;
(7)尽可能减少不必要的filesort;

实验准备:向表中插入50w条数据

在做优化之前,要准备大量数据。接下来创建两张表,并往员工表里插入50W数据,部门表中插入1W条数据。
怎么快速插入50w条数据呢? 存储过程
怎么保证插入的数据不重复?函数

部门表:

  • id:自增长

  • deptName:随机字符串,允许重复

  • address:随机字符串,允许重复

  • CEO:1-50w之间的任意数字

员工表:

  • id:自增长
  • empno:可以使用随机数字,或者从1开始的自增数字,不允许重复
  • name:随机生成,允许姓名重复
  • age:区间随机数
  • deptId:1-1w之间随机数

总结: 需要产生随机字符串和区间随机数的函数。

创建表

CREATE TABLE `dept` (`id` INT(11) NOT NULL AUTO_INCREMENT,`deptName` VARCHAR(30) DEFAULT NULL,`address` VARCHAR(40) DEFAULT NULL,ceo INT NULL ,PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1;CREATE TABLE `emp` (`id` INT(11) NOT NULL AUTO_INCREMENT,`empno` INT NOT NULL ,`name` VARCHAR(20) DEFAULT NULL,`age` INT(3) DEFAULT NULL,`deptId` INT(11) DEFAULT NULL,PRIMARY KEY (`id`)#CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1;

创建函数

-- 查看mysql是否允许创建函数:
SHOW VARIABLES LIKE 'log_bin_trust_function_creators';
-- 命令开启:允许创建函数设置:(global-所有session都生效)
SET GLOBAL log_bin_trust_function_creators=1; 
-- 随机产生字符串
DELIMITER $$
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN    DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';DECLARE return_str VARCHAR(255) DEFAULT '';DECLARE i INT DEFAULT 0;WHILE i < n DO  SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));  SET i = i + 1;END WHILE;RETURN return_str;
END $$-- 假如要删除
-- drop function rand_string;
-- 用于随机产生区间数字
DELIMITER $$
CREATE FUNCTION rand_num (from_num INT ,to_num INT) RETURNS INT(11)
BEGIN   DECLARE i INT DEFAULT 0;  SET i = FLOOR(from_num +RAND()*(to_num -from_num+1));
RETURN i;  
END$$-- 假如要删除
-- drop function rand_num;

创建存储过程

-- 插入员工数据
DELIMITER $$
CREATE PROCEDURE  insert_emp(START INT, max_num INT)
BEGIN  DECLARE i INT DEFAULT 0;   #set autocommit =0 把autocommit设置成0  SET autocommit = 0;    REPEAT  SET i = i + 1;  INSERT INTO emp (empno, NAME, age, deptid ) VALUES ((START+i) ,rand_string(6), rand_num(30,50), rand_num(1,10000));  UNTIL i = max_num  END REPEAT;  COMMIT;  
END$$-- 删除
-- DELIMITER ;
-- drop PROCEDURE insert_emp;
-- 插入部门数据
DELIMITER $$
CREATE PROCEDURE insert_dept(max_num INT)
BEGIN  DECLARE i INT DEFAULT 0;   SET autocommit = 0;    REPEAT  SET i = i + 1;  INSERT INTO dept ( deptname,address,ceo ) VALUES (rand_string(8),rand_string(10),rand_num(1,500000));  UNTIL i = max_num  END REPEAT;  COMMIT;  
END$$-- 删除
-- DELIMITER ;
-- drop PROCEDURE insert_dept;

调用存储过程

-- 执行存储过程,往dept表添加1万条数据
CALL insert_dept(10000); -- 执行存储过程,往emp表添加50万条数据,编号从100000开始
CALL insert_emp(100000,500000); 

批量删除表索引

-- 批量删除某个表上的所有索引
DELIMITER $$
CREATE PROCEDURE `proc_drop_index`(dbname VARCHAR(200),tablename VARCHAR(200))
BEGINDECLARE done INT DEFAULT 0;DECLARE ct INT DEFAULT 0;DECLARE _index VARCHAR(200) DEFAULT '';DECLARE _cur CURSOR FOR SELECT index_name FROM information_schema.STATISTICS WHERE table_schema=dbname AND table_name=tablename AND seq_in_index=1 AND index_name <>'PRIMARY'  ;DECLARE CONTINUE HANDLER FOR NOT FOUND set done=2 ;      OPEN _cur;FETCH _cur INTO _index;WHILE  _index<>'' DO SET @str = CONCAT("drop index ",_index," on ",tablename ); PREPARE sql_str FROM @str ;EXECUTE sql_str;DEALLOCATE PREPARE sql_str;SET _index=''; FETCH _cur INTO _index; END WHILE;CLOSE _cur;
END$$
-- 执行批量删除:dbname 库名称, tablename 表名称
CALL proc_drop_index("dbname","tablename"); 

最左前缀法则示例

假设index(a,b,c)

Where语句索引是否被使用
where a = 3Y,使用到a
where a = 3 and b = 5Y,使用到a,b
where a = 3 and b = 5 and c = 4Y,使用到a,b,c
where b = 3 或者 where b = 3 and c = 4 或者 where c = 4N
where a = 3 and c = 5使用到a, 但是c不可以,b中间断了
where a = 3 and b > 4 and c = 5使用到a和b, c不能用在范围之后,b断了
where a is null and b is not nullis null 支持索引 但是is not null 不支持,所以 a 可以使用索引,但是 b不一定能用上索引(8.0)
where a <> 3不能使用索引
where abs(a) =3不能使用 索引
where a = 3 and b like ‘kk%’ and c = 4Y,使用到a,b,c
where a = 3 and b like ‘%kk’ and c = 4Y,只用到a
where a = 3 and b like ‘%kk%’ and c = 4Y,只用到a
where a = 3 and b like ‘k%kk%’ and c = 4Y,使用到a,b,c

一般性建议

Ø 对于单键索引,尽量选择过滤性更好的索引(例如:手机号,邮件,身份证)Ø 在选择组合索引的时候,过滤性最好的字段在索引字段顺序中,位置越靠前越好。Ø 选择组合索引时,尽量包含where中更多字段的索引Ø 组合索引出现范围查询时,尽量把这个字段放在索引次序的最后面Ø 尽量避免造成索引失效的情况

开始实验

删除索引: drop index idx_age_name_deptid on emp;
创建索引:CREATE INDEX idx_age_deptid_name ON emp (age,deptid,NAME);

1、无过滤不索引

EXPLAIN SELECT * FROM emp ORDER BY age,deptid; 
EXPLAIN SELECT * FROM emp ORDER BY age,deptid LIMIT 10; 增加过滤条件,使用上索引了。
EXPLAIN SELECT age FROM emp where age>1000 ORDER BY age,deptid,name;

2、查询条件与筛选条件

const查询排序后回表操作,不会filesort
EXPLAIN SELECT * FROM emp WHERE age=45 ORDER BY age,deptid,NAME; range查询,Using index condition 没有完全使用索引
EXPLAIN SELECT * FROM emp WHERE age>45 ORDER BY age,deptid,NAME;
range查询,Using where; Using index 完全使用索引
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age,deptid,NAME;

3、顺序错 filesort

正常情况
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age,deptid,NAME;
order by顺序变化会导致filesort
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY deptid,age,NAME;

4、order by非最左 filesort

EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY deptid,NAME;

5、方向反 必排序

8.0为Backward index scan 倒序索引
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age desc,deptid desc,NAME desc方向反 产生filesort
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age desc,deptid desc,NAME asc;

二、数据库索引的原理?创建索引的缺点是什么,什么情况索引失效?优化数据库的方法有哪些?

1、数据库索引的原理?

(1)以MySQL为例,默认引擎innoDB使用了b+树实现索引,在索引查找时,实现了log(n)的时间复杂度;
(2)聚簇索引记录了主键ID【完整数据】,非聚簇索引的索引树中记录数据【索引字段+主键】;
(3)在聚簇索引的叶子节点中记录了完整的值,非聚簇索引的叶子节点记录的是主键以及索引字段,如果需要完整值的话需要回表操作,即使用主键去聚簇索引中再次查找完整数据;
(4)索引的叶子节点以链表的形式存储,方便顺序查找和排序;

2、创建索引的缺点是什么?

(1)会占用空间;(2)更新时会级联更新索引;(3)高并发写影响性能;

3、什么情况索引失效?

(1)计算、函数导致索引失效;(2)LIKE以%开头索引失效;(3)不等于【!=】;(4)IS NOT NULL 可能失效【不同版本和数据决定】IS NULL 有效;(5)类型转换导致索引失效;(6)数据库优化器觉得不用索引更快的时候失效;

4、优化数据库的方法有哪些?

(1)硬件【主要在存储层优化】;(2)网络;(3)操作系统调优;(4)表结构设计优化;(5)sql优化;(6)减少函数使用;(7)索引优化;(8)大字段及全文检索优化;(9)连接池优化;(10)事务优化;(11)数据库集群化;(12)加入缓存;(13)冷热存储;(14)分库分表;

三、数据连接池的工作机制是什么?

答:
1. 预先创建好一些数据库连接,放到连接池中
2. 连接池中设置最小连接数和最大连接数
3. 最小连接不断开和数据库的连接
4. 超过最小链接的那些线程,在长时间不使用时会被回收,也就是断开和数据库的连接
5. 所有向数据库发送请求的业务必须通过连接池获得数据库连接
6. 当连接全部在使用中,可以使用队列等待

四、说一下MySQL中事务的实现原理

Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问

InnoDB是一个多版本的存储引擎。它保存有关已更改行的旧版本的信息,以支持并发和回滚等事务特性。这些信息存储在一个称为回滚段的数据结构中的系统表空间或undo表空间中。参见第14.6.3.4节“撤消表空间”。InnoDB使用回滚段中的信息来执行事务回滚所需的撤消操作。它还使用这些信息构建行的早期版本,以实现一致的读取

MVCC 的实现依赖于:隐藏字段、Read View、undo log

隐藏字段

  • A 6-byte DB_TRX_ID 用来标识最近一次对本行记录做修改 (insert 、update) 的事务的标识符 ,即最后一次修改本行记录的事务 id。 如果是 delete 操作, 在 InnoDB 存储引擎内部也属于一次 update 操作,即更新行中的一个特殊位 ,将行标识为己删除,并非真正删除。
  • A 7-byte DB_ROLL_PTR 回滚指针,指向该行的 undo log 。如果该行未被更新,则为空.
  • A 6-byte DB_ROW_ID 如果没有设置主键且该表没有唯一非空索引时,InnoDB 会使用该 id 来生成聚簇索引.

Read View

不同的事务隔离级别中,当有事物在执行过程中修改了数据(更新版本号),在并发事务时需要判断一下版本链中的哪个版本是当前事务可见的。为此InnoDB有了ReadView的概念,使用ReadView来记录和隔离不同事务并发时此记录的哪些版本是对当前访问事物可见的。

undo log

除了用来回滚数据,还可以读取可见版本的数据。以此实现非锁定读

答:
1. mysql是由mvcc实现的事务控制
2. MVCC 的实现依赖于:隐藏字段、Read View、undo log
3. 在不同的事务隔离级别下通过设置readview内容,控制了哪些数据可见于不可见

五、JVM

1、JVM 内存模型中,为什么要区分新生代和年老代,对于新生代,为什么又要区分eden 区survial区?

在这里插入图片描述

个人理解答案:

1、主流垃圾回收器cms g1都使用了分代收集算法;
2、正常系统运行时会有海量临时对象产生,这些对象短期内大部分就会失效,对于这些对象我们把他们临时放到新生代;
3、新生代满了之后需要清理垃圾对象,我们会吧有效对象复制到老年代,以便后续继续使用;
4、为了更有效的区分哪些对象应该被复制到老年代,所以在新生代划分出了eden区和s0 s1区;
5、细化后的新生代内部被再次划分以便保证高速读写同时内存连续;
【1】新对象会被保存到eden区(开始是空的所以内存连续),eden区满了会把有效对象复制到s0(s0也是空的所以也是连续空间);
【2】清空eden区(再次写入时又是连续空间)
【3】s0 和 s1在命名上互换,原来的s1等待写入(空的)
【4】eden区再次满了,重复上面步骤

文心一言AI答案:

在这里插入图片描述

2、说一下你理解的JVM原理?

JVM 运行时数据区域包含堆、栈、本地方法栈、方法区

在这里插入图片描述

在这里插入图片描述

答案:jvm是Java虚拟机,我们的class文件运行在虚拟机上,通过虚拟机解决了跨平台的问题,jvm中有jmm来管理Java内存访问的方式,不同的jvm实现性能关注有差异,现在主流的实现是Hotspot,垃圾回收器是G1,jvm运行时内存中分为方法区,堆,栈,本地方法栈,执行代码时需要执行引擎。

3、请简述一下JVM 加载 class 文件的原理机制

关键点:1. 类加载器;2. 魔数;3. 元空间:负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。

魔数

  • Class文件开头的四个字节的无符号整数称为魔数(Magic Number)。
  • 魔数是Class文件的标识。值是固定的,为0xCAFEBABE
  • 如果一个Class文件的头四个字节不是0xCAFEBABE,虚拟机在进行文件校验的时候会报错。使用魔数而不是扩展名来识别Class文件,主要是基于安全方面的考虑,因为文件扩展名可以随意更改。
    在这里插入图片描述

类加载器分为四种:前三种为虚拟机自带的加载器。

  • 启动类加载器(Bootstrap)C++

    负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

    也叫系统类加载器,负责加载classpath中指定的jar包及目录中class

  • 扩展类加载器(Extension)Java

    负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

  • 应用程序类加载器(AppClassLoader)Java

  • 用户自定义加载器 Java.lang.ClassLoader的子类,用户可以定制类的加载方式

工作过程:

  • 1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
  • 2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
  • 3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
  • 4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载
  • 5、如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException

其实这就是所谓的双亲委派模型。简单来说:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上
在这里插入图片描述
好处:防止内存中出现多份同样的字节码(安全性角度)
比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object对象。

六、选择题

1、典型的JDBC程序按(DBECFA)顺序编写( 排序)

A.释放资源
B.获得与数据库的物理连接
C.执行SQL命令
D.注册JDBC Driver
E.创建不同类型的Statement
F.如果有结果集,处理结果集

2、下列语句哪一个正确(b)

A.Java 程序经编译后会产生 machine code
B.Java 程序经编译后会产生 byte code
C.Java 程序经编译后会产生 DLL
D.以上都不正确

3、存在使i+1<i的数吗?存在

int i = Integer.MAX_VALUE;
System.out.println(i>i+1);true

4、Integer和int的区别?

1、Integer是int的包装类,int则是Java的一种基本的数据类型;
2、integer实际是对象的引用,当new一个integer时,实际上生成一个指针指向对象,而int则直接存储数值;
3、integer的默认值是null,而int的默认值是0;

5、jsp的八个隐含对象有哪些?

关键点:

  1. jsp本质上就是servlet
  2. 答不上来关系也不大

答:

1 pageContext

类型:PageContext

代表:当前页面的上下文

作用:可以获取到页面中的其他隐含对象,同时它还是一个域对象。

2 request

类型:HttpServletRequest

代表:请求

作用:可以获取用户发送的请求信息,它也是一个域对象。

3 session

类型:HttpSession

代表:当前会话

作用:可以作为域对象,用来共享数据。

4 application

类型:ServletContext

代表:代表整个WEB应用

作用:是JavaWeb中最大的域对象。

5 response

类型:HttpServletResponse

代表:响应

作用:向浏览器发送响应信息

6 out

类型:JspWriter

代表:输出流

作用:可以向页面输出内容

7 config

类型:ServletConfig

代表:当前JSP的配置信息

作用:可以获取到Servlet标签中初始化参数

8 page

类型:Object 在service方法中有如下代码 Object page = this;

代表:代表当前JSP的对象

9 exception

类型:Throwable

代表:异常信息

作用:获取页面中的异常

6、下面程序能正常运行吗?

  1. null 是可以被强转成任何类型的;2. 静态方法不需要实例对象
public class NULL {public static void haha() {System.out.println("haha");}public static void main(String[] args) {((NULL)null).haha();}
}

七、A 系统远程调用 B 系统的接口,A 系统在完成调用之后,需要更新A 系统本地表

问题1:常见的远程调用有几种?

1. 自定义协议实现C/S RPC调用(实现复杂,需解决的问题多)
2. UDP广播类型(常见用于即时通讯类,速度快,但需要二次确认)
3. 目前主流的基于http协议调用(Restful风格的api,springcloud微服务调用使用的就是http)
4. dubbo协议(阿里出品,长连接,二进制封装数据,性能较高)
5. soap协议(古老的webservice系列框架,基于xml实现数据封装,http协议传输)
6. 异步响应式(WebFlux+Spring Data Reactive)
7. 服务器推(不主动调用,常见系统通知类)

问题2:对于有这些外部衔接的方法需要注意哪些问题?请写出注意问题及伪代码?

1、写好接口文档,方便后续维护和团队协作

2、统一化的报文结构

3、标准化的服务状态码

 status_code 200;//请求成功

4、统一化请求日志记录及异常记录

GlobalExceptionHandler...
logger.error("服务异常",exception);

5、当请求延迟过高,可以快速失败
6、重试机制

// 服务列表
serverList = {ser1,ser2,ser3}
retrycount = 0;
retrymax=10;
maxrequesttime = 200ms;
getxxoo(){try{// 尝试请求数据calldata(serverList)}catch (请求失败 500类异常 || 请求超时 calldata的网络请求方法中){// 拦截器记录日志serverList.remove(刚才请求的服务器)// 重试次数过多if (retrycount == retrymax)return "当前访问不可用稍后再试"retrycount ++;递归调用本方法}
}

7、事务问题,可回滚

getData(){分布式事务开启get1();get2();get3();事务结束要么全成功 要么全失败修改数据时使用 tryModify() 临时保存数据或通过Seata类似的框架实现
}

8、数据一致性问题

//有并发修改数据时,如果需要保证一致性,需要使用分布式锁
//修改方法
modifyxx(){// 尝试加锁boolean haslock = tryLock(id)if(haslock){httppost(url,data)releaseLock(id)}else{// 提示用户一会再试试// 尝试再次获取锁}
}

八、在如下代码中,当调用insertA 方法的时候,是否能在当insertA 方法调用insertB的时候,如果insertB 插入b表的时候出现异常,能否保证 insertA中的a 表插入成功,如果不能,应该如何修改。

@Service
@Transactional
public class TestServie {@Autowiredprivate JdbcTemplate jt;public void insertA(){jt.execute("insert into a(m,n)values(1,2)");insertB();}public void insertB(){jt.execute("insert into b(h,i)values(1,2)");}
}

答案:不能,在类上使用了@Transactional注解,默认开启了全局读写事务,因此可以将@Transactional加在方法上即可。

九、数据库三范式是什么?

1、第一范式:单表(字段)拆分到不可拆分为止【有主键,具有原子性,字段不可分割】;
2、第二范式:每一行数据唯一性;
3、第三范式:单行数据中保留唯一主键,建立外键关联表;

答案:
1. 数据库三范式是设计数据库表的方法论,能够充分的利用关系型数据库把实体有机的关联起来
2. 降低耦合度节省存储空间

十、浅谈ReentrantLock的设计

  1. ReentrantLock 是在多线程竞争资源时使用的锁,他是一个独占锁、可重入锁,也是悲观锁
  2. ReentrantLock 支持公平锁,对公平和非公平锁有不同的实现逻辑
  3. ReentrantLock 使用 aqs(AbstractQueuedSynchronizer)来实现的获取锁的线程队列等待的过程
  4. 内部使用了原子操作类 cas 比较线程与对应的锁关系
  5. 内部支持newCondition来灵活的控制获取到锁的线程的阻塞与释放

十一、值传递和引用传递问题

关键点:1. 引用传递;2. 堆栈内存分析

public class demo01 {public static void main(String args[]) {StringBuffer a = new StringBuffer("A");StringBuffer b = new StringBuffer("B");operater(a,b);System.out.println(a+" "+b);// AB B}public static void operater(StringBuffer x, StringBuffer y) {// x 是一个列表对象,x.append(y) 实际上是在修改了 x 对象本身,而不是替换整个对象。因此,当您在 operater 方法中调用 x.append(y),x 列表会被修改为 ['A', 'B']。由于 a 和 x 引用同一个对象,它们指向同一个内存地址。所以当您在 operater 方法中修改了 x,也会影响到 main 方法中的 ax.append(y);// 将x赋值给了y,这意味着y也会引用"AB"。然而,需要注意的是,这个赋值操作只会在operater方法内部起作用,并不会影响到main方法中的b对象。y = x;System.out.println(x+" "+y);// AB AB}
}

十二、多线程

1、多线程中 start()方法和 run()方法的区别是什么?

答:
1. start用来启动线程,改变的是线程的状态,由就绪进入执行
2. run方法中包含要执行的代码,在执行状态时运行里面的代码,方法返回值是void

2、创建线程有几种方式?

(1)使用Thread类创建线程

public class MyThread extends Thread {  public void run() {  System.out.println("使用thread方式创建线程"); }  
}  
// 创建并启动线程  
MyThread thread = new MyThread();  
thread.start();

(2)使用Runnable接口创建线程

public class MyRunnable implements Runnable {  public void run() {  System.out.println("使用Runnable方式创建线程");  }  
}  
// 创建并启动线程  
MyRunnable runnable = new MyRunnable();  
Thread thread = new Thread(runnable);  
thread.start();

(3)使用Executor框架创建线程

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  public class MyThread implements Runnable {  public void run() {  System.out.println("使用ExecutorService方式创建线程");}  public static void main(String[] args) {  // 创建线程池  ExecutorService executor = Executors.newFixedThreadPool(10);  // 提交任务到线程池  executor.submit(new Mythread());  // 关闭线程池  executor.shutdown();  }  
}

3、简单写一个会导致死锁的程序

  1. 获得锁后不释放,其他线程一直拿不到锁
  2. 解决:不要嵌套获得多个锁
	static Object lockA = new Object();static Object lockB = new Object();public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread() + " 尝试获取锁A");synchronized (lockA){System.out.println(Thread.currentThread() + " 获取到了锁A");try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Thread.currentThread() + " 尝试获取锁B");synchronized (lockB){System.out.println(Thread.currentThread() + " 获取到了锁B");}}}}).start();new Thread(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread() + " 尝试获取锁B");synchronized (lockB){System.out.println(Thread.currentThread() + " 获取到了锁B");try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Thread.currentThread() + " 尝试获取锁A");synchronized (lockA){System.out.println(Thread.currentThread() + " 获取到了锁A");}}}}).start();}

4、多线程变量同步

  1. 共享变量在多线程读取的时候,会被拉倒线程本地,white 在执行时,一直使用的都是本地变量的值,所以后续更改,线程内一直访问不到最新变量,程序会卡死
  2. 给变量增加 volatile关键字,保证多线程之间 变量可见性
public class ThreadSafeCache {private int result;public int getResult() {return result;}public synchronized void setResult(int result) {this.result = result;}public static void main(String[] args) {ThreadSafeCache threadSafeCache = new ThreadSafeCache();for (int i = 0; i < 8; i++) {new Thread(() -> {while (threadSafeCache.getResult() < 100) {}System.out.println("我执行了");}).start();}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}threadSafeCache.setResult(200);}
}

5、定义了一个类T,其中定义了一个synchronized 方法do(); A=newT();B = new T()。当一个线程进入A对象的 do 方法后,另一个线程是否可进入B对象的do 方法?互不影响

1. synchronize 普通方法,锁的是当前对象
2. synchronize 静态方法,锁的是class
3. 同步代码块,可以手动指定锁对象是啥

6、多线程有几种实现方法,都是什么?

  1. 实现Runnable接口 void返回值
  2. 实现Callable接口 可以指定返回值
/*** 1. 创建Callable的实现类,并重写call()方法,该方法为线程执行体,并且该方法有返回值*/
class MyCallableThread implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println(Thread.currentThread().getName() + "执行了!");return 200;}
}public class CallableDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {// 2. 创建Callable的实例,并用FutureTask类来包装Callable对象// 3. 创建FutureTask对象,需要一个Callable类型的参数FutureTask task = new FutureTask<Integer>(new MyCallableThread());// 4. 创建多线程,由于FutureTask的本质是Runnable的实现类,所以第一个参数可以直接使用tasknew Thread(task, "threadName").start();//new Thread(task, "threadName2").start();/*while (!task.isDone()) {System.out.println("wait...");}*/System.out.println(task.get());System.out.println(Thread.currentThread().getName() + " over!");}
}

7、编写一个基于线程安全的懒加载单例模式

关键点:1. 多线程访问;2. 防止直接new对象;3. 使用锁;4. 内部类加载实现、cas实现等

public class Test03 {private Test03(){}private static Test03 instance = null;public static Test03 getInstance(){//有可能在多线程访问的时候 重复new了对象if(instance == null){// 有可能有多个线程 进入抢锁等待状态synchronized (Test03.class){if (instance == null){instance = new Test03();}else {return instance;}}}return instance;}
}

十三、对于高并发、高可用问题的常用处理方式

1、对于高并发

关键点:

  1. 寻找瓶颈
  2. 分治思想,业务拆分,流程拆分
  3. 扩容
  4. 限流
  5. 分流 ,cdn 缓存
  6. 流量清洗 waf
  7. 多级缓存设计 后端缓存,客户端缓存
  8. 日志溯源
  9. 资源隔离
  10. 弹性扩缩容
  11. 降级处理 前后端 兜底数据

2、对于高可用

  1. 容器化管理 HA
  2. keepalived

十四、哪一个List实现了最快插入?

arraylist :数组实现的,查询,修改比较快
linkedlist:链表实现,插入,删除比较快,直接在最后插入数据即可
vector:jdk1.0就有 线程安全,效率特别低

十五、同步有几种实现方法,都是什么?

非阻塞

1. volatile
2. cas及atomic系列实现

阻塞

1. wait()
2. sleep
3. synchronized
4. Lock 的实现1. ReentrantLock2. ReentrantReadWriteLock 等3. condition.await()
5. CountDownLatch
6. CyclicBarrier
7. Semaphore
8. BlockingQueue

十六、SpringBoot

1、springboot是如何管理版本依赖的?

1、springboot底层使用Maven管理依赖,通过控制pom.xml父子关系来完成细节配置,在父pom中定义具体框架和版本号以及额外的信息;
2、提供了很多场景的spring-boot-starter的pom.xml文件,来标准化的引入依赖避免冲突;

2、什么是自动配置?

关键点:

1. 看springboot的源码
2. @SpringBootApplication 中包含的@EnableAutoConfiguration,@SpringBootConfiguration,@ComponentScan 注解
3. @EnableAutoConfiguration 开启自动配置功能 内部还包含 @AutoConfigurationPackage、@Import1. @AutoConfigurationPackage 中 @Import(AutoConfigurationPackages.Registrar.class) 引入了 Registrar.class 完成批量注册,默认扫描主启动类的包@Bean或者@Compont等注解2. @Import(AutoConfigurationImportSelector.class)
4. @ComponentScan 扫描被@Compent(@Service@Controller)注解的bean 加载到容器中
5. @SpringBootConfiguration 表示这是一个SpringBoot的配置类

答:

1. 所加载使用的jar包 如果是比较常见的,spring都提供了默认配置,也就是不像以前一样需要把框架的每一个属性都要配置一遍,主要目的是简化开发
2. springboot 通过在启动类上添加注解 @SpringBootApplication 完成自动配置
3. 内部完成了读取每个jar包下的`META-INF/spring.factories`和spring-boot-autoconfigure-2.6.7.jar中的默认配置

3、起步依赖?

指的是各种starter重点是pom.xml,其中包含了框架所需要的其他依赖以及默认配置文件,不需要我们手动配置了。

4、什么是Spring的依赖注入?有哪些方法进行依赖注入?

依赖注入是指将依赖的对象实例交给spring帮我们注入管理,从而释放对对象的管理权,比如可以统一替换接口的实现,更高效的开发程序。
1、set方法注入;2、构造方法注入;3、@Autowired【用于自动装配bean,它可以根据类型进行注入】和@Resource【用于获取指定名称的bean,它可以根据名称进行注入】

5、Spring的AOP的使用情景有哪些?简述其实现原理

在这里插入图片描述

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

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

相关文章

解决分类任务中数据倾斜问题

大家好&#xff0c;在处理文本分类任务时&#xff0c;基准测试流行的自然语言处理架构的性能是建立对可用选项的理解的重要步骤。在这里&#xff0c;本文将深入探讨与分类相关的最常见的挑战之一——数据倾斜。如果你曾经将机器学习&#xff08;ML&#xff09;应用于真实世界的…

VS+QT+PCL点云显示转网格表面体窗体实现

程序示例精选 VSQTPCL点云显示转网格表面体窗体实现 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<VSQTPCL点云显示转网格表面体窗体实现>>编写代码&#xff0c;代码整洁&…

watch避坑,使用computed进行处理数据

业务场景&#xff1a;在vue中监听el-input 中的字数有没有超过60&#xff0c;如果超过60字时将60后面的字变为 “>>” 符号&#xff0c;以此实现预览苹果手机推送摘要场景。 错误&#xff1a;开始的逻辑是使用watch监听&#xff0c;检查length超过60直接 加上符号&#x…

python 网络编程

TCP编程 客户端 创建TCP连接时&#xff0c;主动发起连接的叫做客户端&#xff0c;被动响应的叫做服务端。当定义一个Socket表示打开一个网络连接&#xff0c;创建一个Socket需要知道目标计算机的IP地址和端口号和对应的协议类型。 # 导入socket库: import socket# 创建一个s…

基于MSP432P401R爬坡小车【2020年电赛C题】

文章目录 一、任务清单1. 硬件部分2. 软件部分 二、OpenMV巡线三、舵机转向四、停止线识别五、技术交流 一、任务清单 1. 硬件部分 主控板&#xff1a; MSP432P401R数据显示&#xff1a; OLED电机&#xff1a; 霍尔编码器电机电池&#xff1a; 7.3V航模电池巡线&#xff1a; …

idea 里 controller service impl mapper xml 切换跳转快捷键

首先在controller层&#xff0c;对着接口点方法的方法上按着ctrl和鼠标左键&#xff0c;你会进入service层。 对着方法ctrlaltb不按鼠标&#xff0c;你会进入impl层。service层的方法上按ctrl和鼠标左键会回到controller&#xff0c;ctrlaltb不按鼠标也会进入到impl层,impl上的…

[Linux]线程基本知识

概念 进程 一个正在执行的程序&#xff0c;它是资源分配的最小单位 进程中的事情需要按照一定的顺序逐个进行 进程出现了很多弊端: 一是由于进程是资源拥有者&#xff0c;创建、撤消与切换存在较大的时空开销&#xff0c;因此需要引入轻型进程&#xff1b; 二是由于对称多…

C++:类和对象(下)---对类和对象深入一些的理解

文章目录 构造函数&#xff1f;初始化列表explicit关键字 匿名对象 构造函数&#xff1f; 初始化列表 前面已然介绍过构造函数&#xff0c;但并未完全结束&#xff0c;构造函数有很多种写法&#xff0c;有带缺省参数的&#xff0c;有全缺省的&#xff0c;不带缺省参数的…但用…

Linux下查找python路径

本地目前装了几个版本的python&#xff0c;这里记录下查找python路径的方法。 1&#xff1a;whereis命令 whereis python2&#xff1a;which命令 which python与whereis相似&#xff0c;但which会返回第一个找到的执行文件的位置。 3&#xff1a;find命令 find命令可以搜索系…

web流程自动化详解

今天给大家带来Selenium的相关解释操作 一、Selenium Selenium是一个用于自动化Web浏览器操作的开源工具和框架。它提供了一组API&#xff08;应用程序接口&#xff09;&#xff0c;可以让开发人员使用多种编程语言&#xff08;如Java、Python、C#等&#xff09;编写测试脚本&…

需求分析案例:消息配置中心

本文介绍了一个很常见的消息推送需求&#xff0c;在系统需要短信、微信、邮件之类的消息推送时&#xff0c;边界如何划分和如何设计技术方案。 1、需求 一个系统&#xff0c;一般会区分多个业务模块&#xff0c;并拆分成不同的业务系统&#xff0c;例如一个商城的架构如下&am…

day45-Netflix Mobile Navigation(左边侧边栏动态导航)

50 天学习 50 个项目 - HTMLCSS and JavaScript day45-Netflix Mobile Navigation&#xff08;左边侧边栏动态导航&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&…

33. 本地记事本

本地记事本 html部分 <button class"add"><i class"iconfont icon-jiahao"></i> </button>css部分 *{margin: 0;padding: 0; } body{background-color: #7bdaf3;display: flex;padding-top: 3rem;flex-wrap: wrap; } .add{pos…

每日一题——删除有序数组中的重复项

删除有序数组中的重复项 题目链接 注&#xff1a;本题所采用的方法是建立在移除元素的基础之上的&#xff0c;如果大家对双指针的方法不大了解&#xff0c;或者不会做《移除元素》这一题&#xff0c;建议先去看看&#x1f449;传送门 具体步骤 定义两个指针slow和fast&#…

【计算机网络】传输层协议 -- UDP协议

文章目录 1. 传输层相关知识1.1 端口号1.2 端口号范围划分1.3 知名端口号1.4 一些相关命令 2. UDP协议2.1 UDP协议格式2.2 UDP协议的特点2.3 什么是面向数据报2.4 UDP的缓冲区2.5 UDP使用注意事项2.6 基于UDP的应用层协议 1. 传输层相关知识 传输层是计算机网络中的一个重要层…

【如何训练一个中英翻译模型】LSTM机器翻译模型部署之onnx(python)(四)

系列文章 【如何训练一个中英翻译模型】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型部署&#xff08;三&#xff09; 【如何…

云原生架构

1. 何为云原生&#xff1f; 很多IT业内小伙伴会经常听到这个名词&#xff0c;那么什么是云原生呢&#xff1f;云原生是在云计算环境中构建、部署和管理现代应用程序的软件方法。 当今时代&#xff0c;众多企业希望构建高度可扩展、灵活且有弹性的应用程序&#xff0c;以便能够快…

13 亿美金买个寂寞?No!AI 时代的数据行业蓄势待发

6月底&#xff0c;全球数据分析领域彻底炸锅了。 两大数据分析企业Databricks和Snowflake纷纷将目光瞄准了AI大模型。要知道&#xff0c;这两位对手平时没少对台戏&#xff0c;为性能、产品和技术经常开撕。但在今年的自家大会上&#xff0c;两家企业却出奇的一致&#xff0c;…

云安全攻防(二)之 云原生安全

云原生安全 什么是云原生安全&#xff1f;云原生安全包含两层含义&#xff1a;面向云原生环境的安全和具有云原生特征的安全 面向云原生环境的安全 面向云原生环境的安全的目标是防护云原生环境中的基础设施、编排系统和微服务系统的安全。这类安全机制不一定会具有云原生的…

Java 设计模式 - 简单工厂模式 - 创建对象的简便之道

简单工厂模式是一种创建型设计模式&#xff0c;它提供了一种简单的方式来创建对象&#xff0c;而无需暴露对象创建的逻辑。在本篇博客中&#xff0c;我们将深入了解简单工厂模式的概念、实现方式以及如何在Java中使用它来创建对象。 为什么使用简单工厂模式&#xff1f; 在软…