目录

hymn

忽有故人心头过,回首山河已是秋。

标签: java (33)

javac 编译内部类

该文章已经加密。

Java 1.8扩容机制怎么确定当前元素在原位置还是原位置+原下标

扩容后新增的那个参与与运算的位是0还是1, 0:原位置,1:原位置加原长度 为什么? 因为扩容后,hashmap的长度变为之前的2倍,长度的位多了一位,比如之前16,是1 0000,扩容后变为32,是10 0000, 而计算key的下标是key的hash值 与(&)长度减一,假如key 的hash值是10,二进制就是1010,下标就是 1010 & 1111,扩容后就是1010 & 1 1111, 就是参与计算 多出来的那个位 是0就是原位置,是1就是原位置加原长度

Java 异常

总体上我们根据Javac对异常的处理要求,将异常类分为2类。 非检查异常(unckecked exception):Error 和 RuntimeException 以及他们的子类。javac在编译时,不会提示和发现这样的异常,不要求在程序处理这些异常。所以如果愿意,我们可以编写代码处理(使用try...catch...finally)这样的异常,也可以不处理。对于这些异常,我们应该修正代码,而不是去通过异常处理器处理 。这样的异常发生的原因多半是代码写的有问题。如除0错误ArithmeticException,错误的强制类型转换错误ClassCastException,数组索引越界ArrayIndexOutOfBoundsException,使用了空对象NullPointerException等等。 检查异常(checked exception):除了Error 和 RuntimeException的其它异常。javac强制要求程序员为这样的异常做预备处理工作(使用try...catch...finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用t....

线程池状态 有更新!

ThreadPoolExecutor继承了AbstractExecutorService,成员变量ctl是一个Integer的原子变量,用来记录线程池状态和线程池中线程个数,类似于ReentrantReadWriteLock使用一个变量来保存两种信息。

java 并发队列总结 有更新!

ConcurrentLinkedQueue 无界非阻塞队列,底层用单链表实现,出队和入队用cas实现。 LinkedBlockingQueue 底层用单链表实现,有界,独占锁实现出队和入队,有两个锁,takeLock和putLock takeLock:控制同时只能有一个线程可以从队头获取元素,其他线程等待 putLock:控制同时只能有一个线程可以从队尾添加元素,其他线程等待 ArrayBlockingQueue 底层数组实现,通过锁实现出队和入队,有界(可以指定,默认Integer.Max_VALUE) PriorityBlockingQueue 带有优先级的无界队列,底层通过二叉树堆实现, DelayQueue 通过 PriorityBlockingQueue来装数据,只有过期的数据才会出队。

AQS 有更新!

AbstractQueuedSynchronizer抽象同步队列简称AQS,它是实现同步器的基础组件,并发包中锁的底层就是使用AQS实现的 AQS是一个FIFO的双向队列,其内部通过节点 head和 tail记录队首和队尾元素,队列元素的类型为 Node。 其中 Node中的 thread变量用来存放进入AQS队列里面的线程; Node节点内部的 SHARED用来标记该线程是获取共享资源时被阻塞挂起后放入AQS队列的, EXCLUSIVE用来标记线程是获取独占资源时被挂起后放入AQS队列的; waitStatus记录当前线程等待状态,可以为 CANCELLED(线程被取消了)、SIGNAL(线程需要被唤醒)、CONDITION(线程在条件队列里面等待)、PROPAGATE(释放共享资源时需要通知其他节点); prev记录当前节点的前驱节点,next记录当前节点的后继节点。 在AQS中维持了一个单一的状态信息 state,可以通过 getState、setState、compareAndSetState函数修改其值。 对于 ReentrantLock的实现来说,state可以用来表示....

ThreadLocal 有更新!

ThreadLocal 只是个工具类,真正的数据都是存在当前的线程内, get() 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; } 当线程调用 get() 时,是返回当前线程的 threadLocals,正真的数据就在这里。 set() public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap ma....

interrupt() interrupted() isInterruped() 区别

void interrupt() 中断线程,例如A线程运行,B线程可以调用A的interrupt()方法来设置线程A的中断标志为true boolean interrupted() 检测当前线程是否被中断,当前线程指的是:在那个线程中调用,不是那个实例的调用。比如在主线程中调用线程 A 的 interrupted ,获取的还是主线程的中断状态。 另外在调用之后会清除当前线程的中断状态,如果当前的中断状态是 true ,调用完后变为 false 。 boolean isInterruped() 检查当前线程是否被中断,这个当前线程指的是:那个线程实例调用的,比如在主线程中调用A的 isInterruped() ,获取的是A线程的中断状态。不清楚当前线程的中断状态。

序列化代理

EnumSet :反序列化使用 反序列化代理 private static class SerializationProxy <E extends Enum<E>> implements java.io.Serializable { /** * The element type of this enum set. * * @serial */ private final Class<E> elementType; /** * The elements contained in this enum set. * * @serial */ private final Enum<?>[] elements; SerializationProxy(EnumSet<E> set) { elementType = set.elementType; elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY); } // instead of cast to E, we should perhaps use ....

使用ThreadLocal

在一个线程中,横跨若干方法调用,需要传递的对象,我们通常称之为上下文(Context),它是一种状态,可以是用户身份、任务信息等。 给每个方法增加一个context参数非常麻烦,而且有些时候,如果调用链有无法修改源码的第三方库,User对象就传不进去了。 Java标准库提供了一个特殊的 ThreadLocal,它可以在一个线程中传递同一个对象。 ThreadLocal实例通常总是以静态字段初始化如下: static ThreadLocal<User> threadLocalUser = new ThreadLocal<>(); 它的典型使用方式如下: void processUser(user) { try { threadLocalUser.set(user); step1(); step2(); } finally { threadLocalUser.remove(); } } 通过设置一个 User实例关联到 ThreadLocal中,在移除之前,所有方法都可以随时获取到该 User实例: void step1() { User u = threadL....