水群笔记

Scroll Down

因为临时线程有超时时间 到了超时时间就会走出死循环 自然就结束了

核心线程是一直在死循环里的 没任务就阻塞 有任务就干活

ThreadPoolExecutor

// 表示已经到达了该移除多余线程的时间
    boolean timedOut = false;
    // 死循环
    for (;;) {
        // 获取 ctl值,没啥好说的
        int c = ctl.get();

        // 如果线程池已经 STOP 了(那么此时队列一定空了)
        // 或者线程池被 SHUTDOWN,并且队列也空了
        // (这个时候,工作线程就应该结束退出了)
        if (runStateAtLeast(c, SHUTDOWN)
            && (runStateAtLeast(c, STOP) || workQueue.isEmpty())) {
            // 就把 ctl 的值 -1(表示worker数量-1,
            // 因为worker数量是 ctl的 后29位,可以直接减)
            decrementWorkerCount();
            // 然后方法返回null,表示没有获取到任务
            return null;
        }
        // 获取工作线程worker的数量
        int wc = workerCountOf(c);

        // 判断是否可以移除线程
        // 1、因为线程池可以设定核心线程可以在一定时间的空闲后移除
        // 2、非核心线程一定会设有时间,在间隔时间后将其移除
        // 先判断 核心线程能否移除  如果不能,再看是否有非核心线程
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
        
        // 如果可以移除线程,并且超时了(正常不会wc>maximumPoolSize)
        // 还有并且,当前线程数 >1,或者队列空了
        // 才 CAS 减去线程数量,表示该线程要结束了
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }
        // try 里面获取任务
        try {
            // 如果可以移除线程
            // 那么就执行 带超时的 poll方法
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                // 否则执行不限制时间的 take方法
                workQueue.take();
            // 获取到了,就可以把任务返回
            if (r != null)
                return r;
            // 否则,将timeOut设置为true
            // 表示超时间了,可以将线程移除
            timedOut = true;









            final void runWorker(Worker w) {
        try {
        // 首先如果 task任务 不为空
        // 如果为空没关系,getTask 拿一个任务不为空就行
        // (注意:获取任务是从阻塞队列里,如果当前没有会先阻塞住)
        // (要是实在没有,就退出循环)
        while (task != null || (task = getTask()) != null) {
           ....................................................
        }
        completedAbruptly = false;
    } finally {
        // 工作线程退休方法
        processWorkerExit(w, completedAbruptly);
    }
}

getTask要阻塞,超时了就会获取到null,就退出循环了

阻塞队列有个方法叫poll

这个方法能带超时时间

队列空了说明 现在不需要临时线程了 获取一段数据拿任务 拿不到就返回null

返回null就走出while死循环
核心线程在take take拿不到就一直阻塞


嗯,对的,这个我理解,我的意思是我用jdk1.8的时候,这句就抛异常了,用11的时候,
就没有这种问题,想问问大家8和11之间,有什么区别导致的这种问题
jdk1.8默认GC是PS+PO,jdk11默认是G1, PS+PO还是分带模型,20M的堆,新老比例1:2,
,新生代6M多,老年代13M多一点,你15M的数组新生代老年代都放不下

加个参数 -Xmn1M 就不报错了
或者-Xmn18M

jdk1.8吗 完整参数-Xms20M -Xmx20 -Xmn1M

lambda搞得死锁
https://blog.csdn.net/weixin_44051223/article/details/105411186
因为lambda会在原来类上生成静态方法,run调用的是生成的静态方法,因为那个类还在执行static静态块,并没有初始化,所以它的方法没法调用,正好阻塞住这个线程,因为join所以这个线程执行不了就没法初始化那个类,所以就造成了死锁.


面试题

Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。
  Set中的对象度不按特定方式排序,并且没有重复对象。但它的有些实现类能对问集合中的答对象按特定方式排序,例如TreeSet类,它可以按照默认排序,也可以通过实专现java.util.Comparator接口来自定义排序方式。
  List中的对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象,如通过list.get(i)方式来获得List集合中的元素。
  Map中的每一个元素包含一个键属对象和值对象,它们成对出现。键对象不能重复,值对象可以重复。

Object 方法
wait和sleep有何区别
stringBuffer StringBuilder
HashMap HashTable
Spring SprindMVC区别
集合 区别
线程池
线程 如何保证线程同步
GC算法
Zk一致性
RPC
MySQL sql如何执行 mycat 分库分表
分库分表
redis 集群 穿透 雪崩 场景
spring starter
jvm
docker原理
设计模式


CMS跟G1的区别?


SpringBoot Component注解和Configuration注解啥区别?
Configuration 在方法嵌套调用的时候,只会new 一个对象,不对产生多例

ConfigurationClassPostProcessor这个类里

你看到代理了 代理肯定增强

他为啥要代理 代理干了啥

就加了俩拦截器

作用就是干你们说的那事

面试官:为什么redis是单进程单线程的?
我:理直气壮说完理由。
面试官:那为什么现在改为多线程了?
我:唉我去。。。。。

所以你要关注新技术 不关注新技术,起码也要关注下主流技术的新版本
比如redis 6.0的release nots 啥的

直接甩他一句,现在随便一台电脑都是多核cpu了

原来的io模型虽然是多路复用模型,都是单线程处理io的accept,read,write事件,命令都是单线程处理。现在是主线程处理accept,read,write单独的线程。也就是reactor模型用最常用的,符合多核cpu的特点,所以性能更好。常用的网络通讯框架基本都是这种模型