安利中国-笔试

安利中国-笔试

2024届校招11月记录(后端)

请描述Java关键字volatile和synchronized,回复1-4题。

volatile是Java提供的一种轻量级的同步机制,它主要有两个功能:保证变量的可见性和禁止指令重排序。synchronized则是Java中的关键字,用于控制并发访问共享资源,是一种重量级的同步机制,它包含两个主要特性:互斥性和可见性。

volatile修饰的int i,多线程执行i++操作,是否存在线程安全问题?为什么?

答:即使i被volatile修饰,多线程执行i++操作也会存在线程安全问题。因为i++并不是原子操作,它包含三个步骤:读取i的值、对i加1、将新的值写入i。即使volatile能保证新值能立即同步到主内存,由于这三个步骤并不是一次性完成,所以仍然存在线程安全问题。

AtomicInteger是通过什么机制保证线程安全的?这个机制原理是什么?

答:AtomicInteger通过CAS(Compare And Swap)机制保证线程安全。CAS是一种无锁的同步机制,它包含三个操作数:内存位置、预期原值和新值。当内存位置的当前值与预期原值相等时,将内存位置的值修改为新值,否则,不做任何操作。这个过程是原子的。

synchronized代码块,多线程执行,拿到锁的线程释放锁后,其余线程会被全部唤醒、还是只唤醒其中一个?

答:synchronized代码块,多线程执行,拿到锁的线程释放锁后,其余线程会被全部唤醒。但是只有一个线程能够获取到锁,其他的线程还是会进入BLOCKED状态。

请接上题,二选一进行回答:

a) 如果全部唤醒,你知道有什么其他的同步方式可以实现只唤醒一个吗?

答:如果想实现只唤醒一个线程,可以使用java.util.concurrent.locks中的Lock和Condition。

b) 如果只唤醒一个,是怎么实现的?

请谈谈你对spring / spring mvc / spring boot / spring cloud的认知,以及四者之间的关联和区别?

答: spring是⼀个IOC容器,⽤来管理Bean,使⽤依赖注⼊实现控制反转,可以很⽅便的整合各种框架,提供AOP机制弥补OOP的代码重复问题、更⽅便将不同类不同⽅法中的共同处理抽取成切⾯、⾃动注⼊给 ⽅法执⾏,⽐如⽇志、异常等 。
springmvc是spring对web框架的⼀个解决⽅案,提供了⼀个总的前端控制器Servlet,⽤来接收请求,然后定义了⼀套路由策略(url到handle的映射)及适配执⾏handle,将handle结果使⽤视图解析技术⽣成视图展现给前端。
springboot是spring提供的⼀个快速开发⼯具包,让程序员能更⽅便、更快速的开发spring+springmvc 应⽤,简化了配置(约定了默认配置),整合了⼀系列的解决⽅案(starter机制)、redis、 mongodb、es,可以开箱即⽤。
Spring Cloud为微服务架构中涉及的配置管理、服务治理、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话等都提供了一种简单的开发方式。

http和https有哪些区别?请回复6-7题。

答: HTTP和HTTPS主要的区别是HTTPS使用了SSL/TLS协议进行了加密处理,比HTTP更安全。HTTPS需要到CA申请证书,一般需要域名、企业资料、个人资料等信息。

https交互过程中,同时用到了非对称加密和对称加密,它们分别是用来做什么的?

答:非对称加密主要用于在握手阶段进行身份验证和协商生成对称加密的密钥,在数据传输阶段使用对称加密保证传输效率。

https一定安全吗?有什么手段可以拦截并解析https交互内容?

答:HTTPS并不一定就是绝对安全的,如果黑客能够拿到服务器的私钥,就可以解析出传输的数据。另外,有一种中间人攻击方式,黑客可以假冒服务器向用户发送自己的公钥,用户使用这个公钥加密数据后,黑客就可以使用自己的私钥解密,然后再用服务器的公钥加密传给服务器。

请根据下表SCORE, STUDENT,回答8-10题。

SCORE:
StudentNo CourseNo score
001 001 78
001 002 67
002 002 67
002 003 52
003 001 81
003 005 92
004 001 85
004 004 76
005 003 58
005 002 61

STUDENT:
name age sex studentNo
钱二 19 F 002
刘一 18 M 001
张三 17 M 003
李四 18 F 004
王五 19 M 005

请写SQL,查询“002”课程分数大于50分的人的姓名、学号、所有课程、课程学分,且按课程学分正序排序。

答:

SELECT s.name, s.studentNo, c.CourseNo, c.score 
FROM STUDENT s 
JOIN SCORE c ON s.studentNo = c.StudentNo 
WHERE c.CourseNo = '002' AND c.score > 50 
ORDER BY c.score;
请写SQL,查询每个学生所有课程的平均分。
SELECT s.name, AVG(c.score) 
FROM STUDENT s 
JOIN SCORE c ON s.studentNo = c.StudentNo 
GROUP BY s.name;
请写SQL,查询“001”课程比“002”课程成绩低的所有学生的学号。
SELECT s1.StudentNo 
FROM SCORE s1 
JOIN SCORE s2 ON s1.StudentNo = s2.StudentNo 
WHERE s1.CourseNo = '001' AND s2.CourseNo = '002' AND s1.score < s2.score;
Mysql的order by和limit同时使用,执行顺序是怎样?

答:Mysql的order by和limit同时使用时,是先执行order by排序,然后再执行limit限制返回的行数。

a) 如果order by先于limit,你认为什么场景下会有什么问题?

如果order by先于limit,那么在数据量很大的情况下,排序操作会消耗大量的内存和CPU资源,可能会导致系统性能下降。

b) 如果limit先于order by,你认为什么场景下会有什么问题?

阅读以下的代码段,请指出存在的问题,并提出修改的建议。

public void writeFile(String fileName, String content) {
        OutputStream out;
        try {
            if (fileName != null && fileName != "") {
                out = new FileOutputStream(fileName);
                out.write(content.getBytes());
            }
        } catch (FileNotFoundException e) {
        } catch (IOException e) {      
            e.printStackTrace();
            }
    }

答:这段代码存在的问题是:没有正确处理异常,当发生FileNotFoundException或IOException时,程序没有进行任何处理,这样可能会导致数据丢失或者程序崩溃。另外,判断字符串是否为空时,应该使用equals()方法,而不是"!="。此外,OutputStream在使用完毕后没有被关闭,这可能会导致资源泄露。修改建议是:添加对异常的处理代码,使用equals()方法进行字符串比较,使用finally块来确保OutputStream在使用完毕后被正确关闭。

请分别描述一下LRU和LFU算法,回答13-14题。

LRU(LeastRecentlyUsed,最近最少使⽤),根据最近被使⽤的时间,离当前最远的数据优先被
淘汰;
LFU(LeastFrequentlyUsed,最近少访问),在⼀段时间内,缓存数据被使⽤次数最少的会被淘汰。

如果作为缓存淘汰算法,LRU和LFU,分别在什么场景下会出现什么缺点?

LRU在缓存数据的访问模式是周期性的时候,可能会导致缓存命中率低,因为每个周期开始时,缓存中的数据都是上个周期的数据,需要重新预热。LFU则在缓存数据的访问频率变化大的时候,可能会导致一些长时间不访问但是访问频率高的数据占据缓存,导致缓存命中率低。

如果不用LRU和LFU,你知道还有什么算法可以用于缓存淘汰?它有什么优缺点?

除了LRU和LFU,还有FIFO(First In First Out)算法,这是最简单的一种缓存淘汰策略,优点是实现简单,缺点是不关心数据的访问模式,可能会导致缓存命中率低。

斐波纳契数列以如下的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2),请写出代码。

输入:n
输出:F(n)
示例1:输入:3,输出:2
示例2:输入:4,输出:3

public int fibonacci(int n) {
    if (n <= 2) {
        return 1;
    }
    int a = 1, b = 1;
    for (int i = 3; i <= n; i++) {
        int temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}

反转链表

输入:head->…->tail
输出:tail->…->head
示例1:输入:head=1->2->3->4->5,输出:tail=5->4->3->2->1

public ListNode reverseList(ListNode head) {
    ListNode prev = null, curr = head;
    while (curr != null) {
        ListNode nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

请编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示。

如:ABCABC….依次递推

public class ABC {
    private int times;
    private int state;
    private Lock lock = new ReentrantLock();
    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();
    private Condition conditionC = lock.newCondition();

    public ABC(int times) {
        this.times = times;
    }

    public void printA() {
        print("A", 0, conditionA, conditionB);
    }

    public void printB() {
        print("B", 1, conditionB, conditionC);
    }

    public void printC() {
        print("C", 2, conditionC, conditionA);
    }

    private void print(String name, int targetState, Condition current, Condition next) {
        for (int i = 0; i < times; ) {
            lock.lock();
            try {
                while (state % 3 != targetState) {
                    current.await();
                }
                state++;
                i++;
                System.out.print(name);
                next.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        ABC abc = new ABC(10);
        new Thread(abc::printA).start();
        new Thread(abc::printB).start();
        new Thread(abc::printC).start();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值