从0到1重新认识Java之实战篇(一)

270 阅读5分钟

这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战

前言

对于在职的我们来说,面试就显得很不方便,所以一般我们都会选择先电话面试,防止对双方的时间浪费,当然了,这也是对我们的基础来一次历练,(勿轻易尝试),毕竟面试才是对掌握的最好检验。

历练

说一下目前负责的项目

公司的业务架构是面向B端的,目前项目负责的是后台管理系统,从入职开始,公司对原有的自研项目进行了重构,正好参与了重构的整个环节。公司所使用的技术栈是Springboot+mybatis,沿用了微服务的架构,采用分布式SpringCloud的框架。

  • 为什么使用mybatis而没有使用mybatisPlus
    • 各有各的说法吧,毕竟MP是基于mybatis的基础上做增强而不做改变;如果公司内部有封装好的mapper的话,大可以使用mybatis+自己内部封装;
    • 有说MP的QueryWrapper很好用,实测真的挺好用的,但是对于部分的coder而言可能需要额外的学习成本,毕竟面向xml的sql是刚需。
    • MP忽略了dao层,使service和dao层的概念模糊化,简单的CRUD用的是mybatis,复杂的还是需要自己写sql

关于Netty的使用

在目前的项目中,我负责的车辆管理系统,由公司外购的第三方gps,并作为终端设备通过netty服务上发数据平台+业务处理实现实时定位+历史数据的功能。

  • Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。

  • 作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty的NIO框架构建。

关于Redis在项目中的使用

  • 在项目中有用到,关于Redis,做短暂的存储

  • 有了解Redis的集群吗

Springboot的启动类的注解

  • @SpringBootApplication

    标注这个类是属于SpringBoot的启动类,从源代码中可以获悉,这个注解被**@Configuration、@EnableAutoConfiguration、@ComponentScan** 注解所修饰,换言之 Springboot 提供了统一的注解来替代以上三个注解。

  • @EnableFeignClients

    加上这个注解,表示这个服务支持调用远程服务

  • @EnableEurekaClient

    这个注解是必须的,表示这个注解要注册到某个Eureka服务(注册中心)中,就相当于是给这个服务在一个群里面加了一个通行证,通行证的具体内容就涉及到了application.yml配置文件里面了

  • @MapperScan

    上面的那个注解是用来标注扫描dao范围的,这里如果你使用的MyBatis的话,需要通过配置文件来指定Mapper和主要的配置文件的位置

  • 手动封装

    自己手动写接口,并封装成注解使用

关于一条SQL如何查看运行情况+索引使用

  • 先查看sql的建表语句,直接查看创建表的时候设置的索引,并校对索引是否生效或者,是否遵循最左原则

  • 使用explain解释函数

    • id:选择标识符
    • select_type:表示查询的类型。
    • table:输出结果集的表
    • partitions:匹配的分区
    • type:表示表的连接类型
    • possible_keys:表示查询时,可能使用的索引
    • key:表示实际使用的索引
    • key_len:索引字段的长度
    • ref:列与索引的比较
    • rows:扫描出的行数(估算的行数)
    • filtered:按表条件过滤的行百分比
    • Extra:执行情况的描述和说明

关于线程池的了解

  • 降低资源消耗:通过重用已经创建的线程来降低线程创建和销毁的消耗
  • 提高响应速度:任务到达时不需要等待线程创建就可以立即执行
  • 提高线程的可管理性:线程池可以统一管理、分配、调优和监控

线程池的参数

  • int corePoolSize 核心线程数
  • int maximumPoolSize 线程池最大线程数
  • long keepAliveTime 线程保持活跃的时间
  • TimeUnit unit keepAliveTime 的时间单位
  • BlockingQueue< Runnable > workQueue 任务挤压队列
  • ThreadFactory threadFactory 线程创建工厂类
  • RejectedExecutionHandler handler 拒绝策略

线程池的最大线程数

创建多少线程合适,要看多线程具体的应用场景。我们的程序一般都是 CPU 计算和 I/O 操作交叉执行的,由于 I/O 设备的速度相对于 CPU 来说都很慢,所以大部分情况下,I/O 操作执行的时间相对于 CPU 计算来说都非常长,这种场景我们一般都称为 I/O 密集型计算;和 I/O 密集型计算相对的就是 CPU 密集型计算了,CPU 密集型计算大部分场景下都是纯 CPU 计算。I/O 密集型程序和 CPU 密集型程序,计算最佳线程数的方法是不同的。

    对于CPU密集型来说,多线程主要目的是提成CPU利用率,保持和CPU核数一致即可。不过在工程上,,线程的数量一般会设置为“CPU 核数 +1”,这样的话,当线程因为偶尔的内存页失效或其他原因导致阻塞时,这个额外的线程可以顶上,从而保证 CPU 的利用率。

    对于IO密集型来说,一般是最佳线程数 =CPU 核数 * [ 1 +(I/O 耗时 / CPU 耗时)]

关于多线程,快的线程先完成,如何等待慢线程一起(除了join方法)

  • 在业务使用中,除了使用join方法去实现以外还可以使用其他方法去替代

  • 使用CountDownLatch()方法

    public class Async implements Runnable {
        private CountDownLatch countDownLatch;
     
        public void setCountDownLatch(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
     
        @Override
        public void run() {
            //业务逻辑
            countDownLatch.countDown();
        }
    }
     
     
    public class MainClass {
        public void call(){
            int size=10;
            CountDownLatch ctl = new CountDownLatch(size);
            for(int i=0;i<size;i++){
                Async async= new Async();
                async.setCountDownLatch(ctl);
                Thread thread=new Thread(async);
                thread.start(); 
            }
            ctl.await(6, TimeUnit.SECONDS); //等待多久为超时
    }
    
  • 由于join方法的底层也是wait()+synchronize同步代码块,所以可以使用这两者去替代。