大乱炖2

标题不记文档,白忙一场

面试题1> 线程 1> 解释一下线程的5种状态 2> 如何实现,3个线程,如何实现,执行完a,再让b和c并行执行2> 线程池 1> 线程池原理 2> 线程池核心参数,比如说任务队列,最大连接数,最小连接数 3> 线程池使用的好处 4> 多线程项目中用的多吗(天气项目、东亚发邮件、山海图鉴异步线程) 5> 多线程死锁的理解,怎么规避死锁 6> lock锁的理解 7> synchronized关键字加在静态方法上,锁的是哪个对象3> java8 1> 新特性都有哪些 2> java8中流Stream的reduce和map区别4> redis 1> 和mysql区别 2> redis怎么范围查询5> SpringBoot 1> 常用注解 2> 配置类自动装配的理解6> 集合 1> Map、Set、List关系 2> 对常用集合类的理解7> java 1> 枚举 2> 设计模式 3> 泛型 4> class中属性加载顺序(ClassLoader类装载器) 6> 项目中怎么调用断开连接(?还是说断开Stream)7> StringBuilder和StringBuffer哪个在项目中用的比较多8> ==和equals的区别2> spring ioc源码6> @ResponseBody的源码实现3> spring如何避免相互依赖4> linux常用命令5> Spring常用注解5> spring怎么整合redis7> 幂等,项目中怎么解决8> MySQL的乐观锁,悲观锁9> redis和数据库,数据不一致问题,项目中怎么解决10> shell常用的命令11> JVM模型12> JVM的垃圾回收过程13> JVM的垃圾回收算法5> 项目相关(4)<就是一个数据终端展示吧,把项目介绍过于简单>7> shell常用命令(1)8> 线程的lock锁(2)华为OD:https://www.zhihu.com/question/360097633答案1解释一下线程的5种状态来源: H:\desktop\面试相关\面试\2020年面试\面试完成后总结\线程状态.jpg概述: 1> 初始状态:线程被NEW出来,但是没有调用start方法 2> 可运行状态:线程调用了start方法后,线程就进入可运行状态,等待CPU调度 3> 运行状态:就绪状态的线程在获得cpu 时间片后变为运行中状态 4> 阻塞状态:分为两种,一种是wait进入的,一种是sleep/join进入的(区别见"其余注意点") 5> 死亡状态:表示该线程已经执行完毕-------------------------------------------------------------------------------------------1> wait和notify 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对 象的等待池,等待池中的线程不会去竞争该对象的锁。 锁池:只有获取了对象的锁,线程才能执行对象的 synchronized 代码,对象的锁每次只有一个线程 可以获得,其他线程只能在锁池中等待(唤醒之后,b、c争夺锁) 区别: notify() 方法随机唤醒对象的等待池中的一个线程,“进入锁池”; notifyAll() 唤醒对象的等待池中的所有线程,进入锁池。 来源:https://blog.csdn.net/meism5/article/details/902382682> join thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。 比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。 注:当前线程,即"main线程",main线程调用了a线程的join方法,直到线程a执行完毕后,才会继续 执行线程main。即b/c线程的start方法。--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------注2:来源(notify和notifyAll的区别):https://blog.csdn.net/meism5/article/details/90238268注3:sleep和wait的区别 -> 都是进入线程的阻塞状态,但sleep线程不会释放对象的锁,wait会让 该线程就会释放该对象的锁后,进入到了该对象的等待池。注4:对象的锁每次只有一个线程可以获得。自己demo中,3个线程都争夺同一个对象的锁,每次只有1个线程可得 示例:H:\desktop\java\java-basic\threadPoolProject\com\guozi\action\ThreadState.java注5:notify随机唤醒对象的等待池中的1个线程,含义为 -> 看"来源(notify和notifyAll的区别)" 如果:在2个线程中,都调用了对象obj的wait方法,则2个线程都释放锁,进入对象obj的等待池中 结果:仅调用一次 obj.notify(),线程 t1 或 t2 中的一个始终在等待被唤醒,程序不终止注6:thread.yeild方法,让线程放弃本次"时间片",从运行状态退回到可运行状态 示例:H:\desktop\java\java-basic\threadPoolProject\com\guozi\action\ThreadState.java注7:wait(),notify(),notifyAll()必须在同步方法/代码块中调用 来源:https://www.cnblogs.com/xiohao/p/7118102.html 来源:https://zhidao.baidu.com/question/144956417.html 示例:H:\desktop\java\java-basic\threadPoolProject\com\guozi\action\ThreadState.java注8:sleep和wait的区别 1> 方法属于谁:sleep是Thread线程类的方法,而wait是Object顶级类的方法。 2> 使用地方:sleep可以在任何地方使用,而wait只能在同步方法或者同步块中使用。 3> 本质区别:在调用sleep()方法的过程中,线程不会释放对象锁。 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用 notify()方法后本线程才进入对象锁定池准备注9:等待池和锁池都是属于对象的如何实现,3个线程,如何实现,执行完a,再让b和c并行执行-----------------------------------------------------------------------------------------注:只使用join就可以实现,线程b、c同时执行。-----------------------------------------------------------------------------------------public class ThreeThread { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new Runnable(){ public void run() { System.out.println(“线程1启动”); for (int i=0;i<3;i++) { try { Thread.sleep(2000); System.out.println(“线程:1工作:”+i+“次”); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(“线程1运行完毕”); } },“t1”); Thread t2 = new Thread(new Runnable(){ public void run() { System.out.println(“线程2启动”); for (int i=0;i<3;i++) { try { Thread.sleep(2000); System.out.println(“线程:2工作:”+i+“次”); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(“线程2运行完毕”); } },“t2”); Thread t3 = new Thread(new Runnable(){ public void run() { System.out.println(“线程3启动”); for (int i=0;i<3;i++) { try { Thread.sleep(2000); System.out.println(“线程:3工作:”+i+“次”); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(“线程3运行完毕”); } },“t3”); t1.start(); t1.join(); t2.start(); t3.start(); }}-----------------------------------------------------------------------------------------注:只使用wait和notifyAll可以实现,但是线程b、c是先后执行,他们被唤醒之后有一个争夺锁的过程。注:使用wait和notifyAll方法配合使用。 使用Thread.yield方法保证,b/c先启动 为保万无一失,可以定义List,b/c启动时执行add方法,a启动时判断list包含了b/c线程名,再向下执行-----------------------------------------------------------------------------------------public class ThreadState { public static void main(String[] args) throws InterruptedException { //锁 Object objLock = new Object(); //线程a Thread t_a = new Thread(new Runnable(){ public void run() { Thread.yield(); synchronized (objLock) { System.out.println(“线程a启动”); for (int i=0;i<3;i++) { try { Thread.sleep(2000); System.out.println(“线程:t_a工作:”+i+“次”); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(“notify阻塞解除”); objLock.notifyAll(); } } },“t1”); //线程b Thread t_b = new Thread(new Runnable(){ public void run() { synchronized (objLock) { System.out.println(“线程b启动”); try { System.out.println(“线程b状态:等待阻塞”); objLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(“线程b状态:阻塞解除”); } } },“t_b”); //线程c Thread t_c = new Thread(new Runnable(){ public void run() { synchronized (objLock) { System.out.println(“线程c启动”); try { System.out.println(“线程c状态:等待阻塞”); objLock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(“线程c状态:阻塞解除”); } } },“t_c”); //注意:先启动b/c,最后启动a //解决:限制性b和c的start方法,最后执行a的start方法 //注意:先启动b/c,最后启动a //解决:a线程run中最开始位置加Thead.yield方法,再次保证先让b和c启动 //注意:线程b、c同时运行 //解决:线程a中使用notifyAll方法,而不是notify方法,notify只能保证唤醒b和c中的一个线程 t_b.start(); t_c.start(); t_a.start(); }}答案2线程池原理来源:http://blog.jboost.cn/threadpool.html来源:H:\desktop\面试相关\面试\2020年面试\面试完成后总结\2、线程池\threadpool.png 1、如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处 理被添加的任务。2、如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。3、如果此时线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于 maximumPoolSize,建新的线程来处理被添加的任务。4、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于 maximumPoolSize,那么通过 handler所指定的策略来处理此任务。5、当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这 样,线程池可以动态的调整池中的线程数。总结即:处理任务判断的优先级为 核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。注:因为创建线程要消耗大量资源,所以能先放在"阻塞队列"中,等核心线程空闲下来,就可以复用原来的线程。 而后再判断是否超过"maximumPoolSize",此时需要新建线程,消耗资源。线程池核心参数,比如说任务队列,最大连接数,最小连接数corePoolSize 核心线程数量,线程池维护线程的最少数量maximumPoolSize 线程池维护线程的最大数量keepAliveTime 线程池除核心线程外的其他线程的最长空闲时间,超过该时间的空闲线程会被销毁unit keepAliveTime的单位,TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDSworkQueue 线程池所使用的任务缓冲队列threadFactory 线程工厂,用于创建线程,一般用默认的即可handler 线程池对拒绝任务的处理策略注:一共7个 核心线程数 最大线程数 最长空闲时间(除核心线程外的其他线程) 最长空闲时间的单位 线程工厂 缓冲队列 饱和策略 注:ThreadPoolExecutor提供了4种策略 ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常(默认) ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务 ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 注:Executors线程工厂类有4种 Executors.newCachedThreadPool(); 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. Executors.newFixedThreadPool(int); 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 Executors.newSingleThreadExecutor(); 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照顺序执行。 Executors.newScheduledThreadPool(int); 创建一个定长线程池,支持定时及周期性任务执行。 注:一般常用的是newFixedThreadPool和newScheduledThreadPool线程池使用的好处来源:http://blog.jboost.cn/threadpool.html1、降低资源消耗。通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。2、提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。3、提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性, 使用线程池可以进行统一的分配、调优和监控多线程项目中用的多吗答:在做过的项目中,都用到过多线程 1> 天气项目 2> 东亚发邮件 3> 山海图鉴异步线程多线程死锁的理解,怎么规避死锁来源:https://blog.csdn.net/ls5718/article/details/51896159注:高赞答案lock锁的理解来源:https://blog.csdn.net/plokmju88/article/details/103354914synchronized关键字加在静态方法上,锁的是哪个对象来源:https://blog.csdn.net/qq_20610631/article/details/81511062答案 springboot注解https://www.cnblogs.com/nihaorz/p/10528121.html@SpringBootApplication@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan@WebServlet、@WebFilter、@WebListener@MapperScan@mapper@ImportResource @Import @PropertySource@Controller@RequestMapping@RequestParam@RequestHeader@CookieValue@ResponseBody@RestController@GetMapping@PostMapping@PutMapping@DeleteMapping@CrossOrigin@Autowired@EnablCaching@PathVariable@Service@Resource@Repository@Transactional1> 启动类启动注解 @SpringBootApplication《监听器/过滤器/拦截器》《配置文件》 《事务》 @Transactional《全局异常》 @ControllerAdvice @ExceptionHandler 1> @SpringBootApplication @SpringBootApplication是一个复合注解, 包含了@SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan这三个注解 2> @SpringBootConfiguration 标注当前类是配置类,这个注解继承自@Configuration。 并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到srping容器中, 并且实例名就是方法名。 3> @EnableAutoConfiguration 是自动配置的注解,这个注解会根据我们添加的组件jar来完成一些默认配置,我们做微服时会添加 spring-boot-starter-web这个组件jar的pom依赖,这样配置会默认配置springmvc 和tomcat。 4> @ComponentScan: 扫描当前包及其子包下被@Component,@Controller,@Service,@Repository注解标记的类并纳入 到spring容器中进行管理。等价于context:component-scan的xml配置文件中的配置项。 5> @WebServlet、@WebFilter、@WebListener Servlet、Filter、Listener 可以直接通过上面注解,注解自动注册,这样通过注解servlet ,拦 截器,监听器的功能而无需其他配置,所以这次相中使用到了filter的实现,用到了这个注解 6> @MapperScan spring-boot支持mybatis组件的一个注解,通过此注解指定mybatis接口类的路径,即可完成对 mybatis接口的扫描 7> @ImportResource @Import @PropertySource 这三个注解都是用来导入自定义的一些配置文件。 1> @ImportResource(locations={}) 导入其他xml配置文件,需要标准在主配置类上。 2> @PropertySource 导入property的配置文件 @PropertySource指定文件路径,这个相当于使用spring的 标签来完成配置项的引入。 3> @import @import注解是一个可以将普通类导入到spring容器中做管理 @import注解是一个可以将普通类导入到spring容器中做管理HTML 11564 字节 582 单词 420 行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值