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—周志明》
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]