java面试知识总结2021

java基础

1.intern()方法的作用

你对intern()的理解,请问下面在jdk8环境下,1和2分别输出是什么,jdk6呢。

public class InternDemo {
    public static void main(String[] args) {
        
        String  builderA  = new StringBuilder("计算机").append("软件").toString();
        System.out.println(builderA);
        System.out.println(builderA.intern());
        System.out.println(builderA.intern() == builderA);//(1)


        String  builderB  = new StringBuilder("ja").append("va").toString();
        System.out.println(builderB);
        System.out.println(builderB.intern());
        System.out.println(builderB.intern()==builderB);//(2)

    }
}

答:jdk6:1:true 2:true jdk8:1:true 2:false
因为“java”在初始化com.misc.Version 的时候就已经加载了,而jdk8取消了老年代,而用元空间,选自《深入理解jvm虚拟机3—周志明》深入理解jvm虚拟机3---周志明

2.你对 LockSupport 的了解,AQS的了解

答:LockSupport 就是线程等待和唤醒的加强版,使用park和unpark,不需要像wait/notifiy 和 await/sinal 一样必须包裹在代码块里。
AQS抽象队列同步器
在这里插入图片描述在这里插入图片描述在这里插入图片描述

package com.luoyi.cn.javaBase.jdkBase;

import java.util.concurrent.locks.LockSupport;

/**
 * @author luoyi
 * @create 2021/5/3-23:32
 * LockSupport 作为底层等待唤醒方法
 **/
public class LockSupportDemo {
    public static void main(String[] args) {
        Thread a = new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"\t 开始");
            LockSupport.park();//不管unpark先后执行,只要执行了,这个就形同虚设 
            System.out.println(Thread.currentThread().getName()+"\t 被唤醒了");

        },"AAA");
        a.start();
        try {  Thread.sleep(1000); } catch (InterruptedException e) {  e.printStackTrace();}
        new Thread(()->{
            LockSupport.unpark(a);//执行先后都不影响a线程唤醒
            System.out.println(Thread.currentThread().getName()+"\t 通知线程");

        },"AAA").start();

    }
}

lock非公平锁下的方法解析
1.以顾客来银行办理业务为例。
在这里插入图片描述2.A线程获取到锁之后,把state置为1,其他线程无法获取锁,B线程进来后,先增加一个傀儡节点,然后再将B线程加入下一个节点,此时队列头指向哨兵节点,队列尾指向线程B节点地址。

final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())//加入队列后如果没有获取到锁,就被park()一直在这个位置阻塞,直到锁释放uppark()去获取锁
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

在这里插入图片描述3.执行线程A空出来后,unpark线程B,B跳出CAS循环,获取锁去执行,头尾指针指向B线程节点,作为新的傀儡节点
在这里插入图片描述4.线程C为第二个节点,原傀儡节点被回收,原线程B位置作为新的傀儡节点。
在这里插入图片描述

3.hashTable 和 concurrentHashMap 的区别,分段锁有什么缺点。

4.简单的redis的LRU算法

package javaBase.com.suanfa;

import java.util.HashMap;
import java.util.Map;

/**
 * @author luoyi
 * @create 2021/5/9-22:47
 **/


public class LruDemoByHead {
    //map负责查找,构建一个虚拟的双向链表,它里面本质是一个个Node节点,作为数据载体
    //1.构造一个Node节点作为数据载体
    class Node<K,V>{
        K key;
        V value;
        Node<K,V> prev;
        Node<K,V> next;

        public Node(){//初始化时前节点等于下一节点
            this.prev = this.next = null;
        }

        public Node(K key,V value){
            this.key = key;
            this.value = value;
            this.prev = this.next = null;
        }
    }
    class DoubleLinkedList<K,V>{

        Node<K,V> head;
        Node<K,V> tail;

        //2.1 构造方法
        public DoubleLinkedList(){
            head = new Node<>();
            tail = new Node<>();
            head.prev = head;
            head.next = tail;
        }
        //2.2 添加到头
        public void addHead(Node<K,V> node){
            node.next = head.next;
            node.prev = head;
            head.next.prev = node;
            head.next = node;
        }
        //2.3 删除节点
        public void removeNode(Node<K,V> node){
            node.next.prev = node.prev;
            node.prev.next = node.next;
            node.prev = null;
            node.next = null;
        }
        //2.4 获得最后一个节点
        public Node getLast(){
            return  tail.prev;
        }
    }
    public int cahesize;
    Map<Integer, Node<Integer,Integer>> map;
    DoubleLinkedList<Integer,Integer> doubleLinkedList;

    public LruDemoByHead(int cacheSize){
        this.cahesize = cacheSize;//坑位
        map = new HashMap<>();//查找
        doubleLinkedList = new DoubleLinkedList<>();
    }
    public int get(int key){
        if(!map.containsKey(key)){
            return -1;
        }
        Node<Integer,Integer> node = map.get(key);
        doubleLinkedList.removeNode(node);
        doubleLinkedList.addHead(node);
        return  node.value;

    }
    public void put(int key,int value){
        if(map.containsKey(key)){
           Node<Integer,Integer> node = map.get(key);
           node.value = value;
           map.put(key,node);
           doubleLinkedList.removeNode(node);
           doubleLinkedList.addHead(node);

        }else{//坑位满了
            if(map.size() == cahesize){
                Node<Integer,Integer> lastNode = doubleLinkedList.getLast();
                map.remove(lastNode.key);
                doubleLinkedList.removeNode(lastNode);

            }
            //这里才是新增一个节点
            Node<Integer,Integer> newNode = new Node<>(key,value);
            map.put(key,newNode);
            doubleLinkedList.addHead(newNode);
        }


    }

    public static void main(String[] args) {
        LruDemoByHead lruDemoByHead = new LruDemoByHead(3);
        lruDemoByHead.put(1,1);
        lruDemoByHead.put(2,2);
        lruDemoByHead.put(3,3);
        System.out.println(lruDemoByHead.map.keySet());

        lruDemoByHead.put(4,4);
        System.out.println(lruDemoByHead.map.keySet());
    }
}

执行结果:
[1, 2, 3]
[2, 3, 4]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值