1.说一说进程调度算法有哪些?

  1. 最短工作优先(SJF);
  2. 最短剩余时间优先(SRTF);
  3. 最高响应比优先(HRRF);
  4. 优先级调度(Priority);
  5. 轮转调度(RR)。

其中,SJF、SRTF为非抢占式调度,其余为抢占式调度。

2.创建线程有哪几种方式

1,继承Thread 2,实现Runnable 3,实现Callable

3.说一说你对双亲委派模型的理解

avatar

上图是类加载器的层次关系,称为类加载器的双亲委派模型。该模型要求除了顶层的启动类加载器外,其它的类加载器都要有自己的父类加载器。

一言概之,双亲委派模型,其实就是一种类加载器的层次关系

  1. 工作过程 **如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此。
  • 因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

  • 在分析类加载的源码时,我们还会再一次细致的提及类加载的过程。

  1. 好处
  • 使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一。 例如 java.lang.Object 存放在 rt.jar 中,如果编写另外一个 java.lang.Object 并放到 ClassPath 中,程序可以编译通过。由于双亲委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 优先级更高,这是因为 rt.jar 中的 Object 使用的是启动类加载器,而 ClassPath 中的 Object 使用的是应用程序类加载器。rt.jar 中的 Object 优先级更高,那么程序中所有的 Object 都是这个 Object。
  • 避免了多份同样字节码的加载,内存是宝贵的,没必要保存相同的两份 Class 对象,例如 System.out.println() ,实际我们需要一个 System 的 Class 对象,并且只需要一份,如果不使用委托机制,而是自己加载自己的,那么类 A 打印的时候就会加载一份 System 字节码,类 B 打印的时候又会加载一份 System 字节码。而使用委托机制就可以有效的避免这个问题。

4.说说你对Spring Boot的理解

Spring Boot:用于快速构建基于spring的应用程序。可以开箱即用,也可以按需改动。提供各种非功能特性。快速生成代码,没有xml配置,简化开发

5.给定一个非负整数 n ,返回 n! 结果的末尾为 0 的数量。

import java.util.*;


public class Solution {
    /**
     * the number of 0
     * @param n long长整型 the number
     * @return long长整型
     */
    public long thenumberof0 (long n) {
        // write code here
        long ans = 0;
        long i = 5;
        while (i <= n) {
            ans += n / i;
            i *= 5;
        }
        
        return ans;
    }
}

6.介绍一下SQL中的聚合函数

  1. COUNT()函数:统计数据表中包含的记录行的总数,或者根据查询结果返回列中包含的数据行数。
  2. AVG()函数:通过计算返回的行数和每一行数据的和,求得指定列数据的平均值。
  3. SUM()函数:是一个求总和的函数,返回指定列值的总和。
  4. MAX()函数:返回指定列中的最大值,不仅适用于查找数值类型,也可应用于字符类型。
  5. MIN()函数:返回查询列中的最小值,不仅适用于查找数值类型,也可应用于字符类型。

7.Java中有哪些集合类

Java中的集合类分为4大类,分别由4个接口来代表,它们是Set、List、Queue、Map。其中,Set、List、Queue、都继承自Collection接口。

· Set代表无序的、元素不可重复的集合。

· List代表有序的、元素可以重复的集合。

· Queue代表先进先出(FIFO)的队列。

· Map代表具有映射关系(key-value)的集合。

Java提供了众多集合的实现类,它们都是这些接口的直接或间接的实现类,其中比较常用的有:HashSet、TreeSet、ArrayList、LinkedList、ArrayDeque、HashMap、TreeMap等。

8.内存泄漏问题该如何解决

内存泄漏,是指不再使用的对象仍然被引用,导致垃圾收集器无法回收它们的内存。由于不再使用的对象仍然无法清理,甚至这种情况可能会越积越多,最终导致致命的OutOfMemoryError。可以按照如下的思路来分析和解决内存泄漏问题:

启用分析器

Java分析器是通过应用程序监视和诊断内存泄漏的工具,它可以分析我们的应用程序内部发生的事情,例如如何分配内存。使用分析器,我们可以比较不同的方法并找到可以最佳利用资源的方式。

启用详细垃圾收集日志

通过启用详细垃圾收集日志,我们可以跟踪GC的详细进度。要启用该功能,我们需要将以下内容添加到JVM的配置当中:-verbose:gc。通过这个参数,我们可以看到GC内部发生的细节。

使用引用对象

我们还可以借助java.lang.ref包内置的Java引用对象来规避问题,使用java.lang.ref包,而不是直接引用对象,即使用对象的特殊引用,使得它们可以轻松地被垃圾收集。

Eclipse内存泄漏警告

对于JDK1.5以及更高的版本中,Eclipse会在遇到明显的内存泄漏情况时显示警告和错误。因此,在Eclipse中开发时,我们可以定期地访问“问题”选项卡,并更加警惕内存泄漏警告。

基准测试

我们可以通过执行基准测试来衡量和分析Java代码的性能。通过这种方式,我们可以比较执行相同任务的替代方法的性能。这可以帮助我们选择更好的方法,并可以帮助我们节约内存。

代码审查

最后,我们总是采用经典的老方式来进行简单的代码演练。在某些情况下,即使这种看似微不足道的方法也有助于消除一些常见的内存泄漏问题。

加分回答

通俗地说,我们可以将内存泄漏视为一种疾病,它通过阻塞重要的内存资源来降低应用程序的性能。和所有其他疾病一样,如果不治愈,随着时间的推移,它可能导致致命的应用程序崩溃。

内存泄漏很难解决,找到它们需要对Java语言有很深的理解并掌握复杂的命令。在处理内存泄漏时,没有一刀切的解决方案,因为泄漏可能通过各种不同的事件发生。

但是,如果我们采用最佳实践并定期执行严格的代码演练和分析,那么我们就可以将应用程序中内存泄漏的风险降到最低。

9.缓存穿透、缓存击穿、缓存雪崩有什么区别,该如何解决?

  • 缓存穿透: 是指缓存和数据库中都没有的数据,而用户不断发起请求。
  • 解决方案:接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 缓存击穿:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期)。这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
  • 解决方案:①设置热点数据永远不过期。②加互斥锁
  • 缓存雪崩:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
  • 解决方案:①设置热点数据永远不过期。②如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。③缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

10.给定一个double类型的数组arr,其中的元素可正可负可0,返回连续子数组累乘的最大乘积。

public double maxProduct(double[] arr) {
    if(arr.length == 0)
        return 0;
         
    double maxpre = arr[0];
    double minpre = arr[0];
    double max = arr[0];
         
    double maxhere, minhere;
         
    for(int i=1; i<arr.length; i++){
        maxhere = Math.max(Math.max(maxpre*arr[i], minpre*arr[i]), arr[i]);
        minhere = Math.min(Math.min(maxpre*arr[i], minpre*arr[i]), arr[i]);
        max = Math.max(max, maxhere);
        maxpre = maxhere;
        minpre = minhere;
    }
    return max;
}