hashmap 存入一个Integer类型的20,查询时使用Long类型的20,能否查出来,为什么?
Integer的equals,很明显不可能查出来
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Thread类中有 定义ThreadLocal.ThreadLocalMap 类型的变量。
简单理解:每个Thread 的对象有个ThreadLocal.ThreadLocalMap 类型的变量,这个是线程隔离的,所以是线程安全的。
注意事项:ThreadLocal使用是经常是线程池,所以需要在使用完之后,做clean的工作。
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
public class ThreadLocal {
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
static class ThreadLocalMap {
// 强 软 弱 虚引用,这里的Entry继承类WeakReference。
static class Entry extends WeakReference> {
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
/**
* The initial capacity -- MUST be a power of two.
*/
private static final int INITIAL_CAPACITY = 16;
private Entry[] table;
......
}
}
public class ThreadContext {
private final static ThreadLocal
软、弱引用适合做缓存。
参考:
强、软、弱、虚引用
Integer和int的区别,以下代码的输出并解释原因:
Integer i1 = new Integer(1000);
Integer i2 = new Integer(1000);
int i3 = 1000;
Integer i4 = 100;
Integer i5 = 100;
System.out.println(i1 == i2);
System.out.println(i1 == i3);
System.out.println(i3 == i1);
System.out.println(i4 == i5);
false // 两个不同对象
true // 自动拆箱, 比较数值
true // 自动拆箱, 比较数值
true // Integer的缓存,这个要注意 -128~127有缓存
参考资料 类初始化过程
class A {
public A(String s) {
System.out.println(s + " Constructor A");
}
}
class B {
public B(String s) {
System.out.println(s + " Constructor B");
}
}
class C {
public C(String s) {
System.out.println(s + " Constructor C");
}
}
class Base {
static A a1 = new A("a1: static");
A a2 = new A("a2: normal");
public Base() {
A a3 = new A("a3: normal");
System.out.println("Constructor Base");
}
static {
System.out.println("Base static block");
}
}
class Derived extends Base {
static B b1 = new B("b1: static");
B b2 = new B("b2: normal");
public Derived() {
B b3 = new B("b3: normal");
System.out.println("Constructor Derived");
}
static {
System.out.println("Derived static block");
}
}
public class Test {
static C c1 = new C("c1: static");
C c2 = new C("c2: normal");
public static void main(String[] args) {
C c3 = new C("c3: normal");
Derived derived = new Derived();
System.out.println("end");
}
}
c1: static Constructor C
c3: normal Constructor C
a1: static Constructor A
Base static block
b1: static Constructor B
Derived static block
a2: normal Constructor A
a3: normal Constructor A
Constructor Base
b2: normal Constructor B
b3: normal Constructor B
Constructor Derived
end
可以写,但是不会被类加载器加载。
双亲委派加载机制决定了:AppClassLoader->ExtClassLoader->BootStrap
String s1 = “ab1”;
String s2 = “ab” + 1;
s1 == s2;
String s3 = “ab”;
String s4 = s3 + 1;
s1 == s4;
final String s5 = “ab”;
String s6 = s5 + 1;
s6 == s1;
true
false
true
如果new的方式的话,底层是char[],能够容纳的最大长度就是Int的最大值。
以常量的方式复制的时候,受java class格式的限制,只能存储到2^16-1
那么双引号里面的ASCII字符最多只能有 65534 个。为什么呢?因为在class文件的规范中, CONSTANT_Utf8_info表中使用一个16位的无符号整数来记录字符串的长度的,最多能表示 65536个字节,而java class 文件是使用一种变体UTF-8格式来存放字符的,null值使用两个字节来表示,因此只剩下 65536- 2 = 65534个字节。也正是变体UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么双引号中字符的数量会更少(一个中文字符占用三个字节)。如果超出这个数量,在编译的时候编译器会报错。
public class StackOverFlow {
public static void test(){
while(true) {
test();
}
}
public static void main(String[] args){
StackOverFlow.test();
}
}
java -Xss160k StackOverFlow
栈溢出
public static void main(String[] args){
// Oom.test();
List list = new ArrayList();
int i = 0;
boolean flag = true;
while (flag){
try {
i++;
list.add(new byte[1024 * 1024]);//每次增加一个1M大小的数组对象
}catch (Throwable e){
e.printStackTrace();
flag = false;
System.out.println("count="+i);//记录运行的次数
}
}
}
java -Xms1m -Xmx1m -XX:+PrintGCDetails Oom
java.lang.OutOfMemoryError: Java heap space
at Oom.main(Oom.java:21)
count=1
java -Xms1m -Xmx1m -XX:MaxMetaspaceSize=4m -XX:+PrintGCDetails StringOomMock
Error occurred during initialization of VM
OutOfMemoryError: Metaspace
JDK8 HotSpot JVM现在使用了本地内存来存储类元数据,被称为Metaspace。
学习资料:
https://ifeve.com/jvm-troubleshooting-guide-4/
ArrayList LinkedList
PriorityQueue优先队列,最大堆、最小堆
hashmap、hashtable区别。
Thread-safe的hashmap有哪些。
ConcurrentHashmap原理。
TreeMap
红黑树
HashMap java8源码详解
ConcurrentHashmap
jdk7 segment 16个不能扩容
jdk8
HashSet
写代码制造一个死锁,并用工具进行检测。
public class DeadLock extends Thread {
private String lock1;
private String lock2;
public DeadLock(String lock1, String lock2) {
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (lock1) {
System.out.println(lock1);
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println(lock2);
}
}
}
public static void main(String[] args) throws InterruptedException {
String lock1 = "lock1";
String lock2 = "lock2";
DeadLock dl1 = new DeadLock(lock1, lock2);
DeadLock dl2 = new DeadLock(lock2, lock1);
dl1.start();
dl2.start();
dl1.join();
dl2.join();
}
}
jps -v | grep DeadLock
jstack -l pid | grep BLOCKED
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007fcabe81bca8 (object 0x000000076ade5a00, a java.lang.String),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007fcabe81bd58 (object 0x000000076ade5a38, a java.lang.String),
which is held by "Thread-1"
ABA
AtomicStampedReference
final int stamp;
AtomicMarkableReference
final boolean mark;