线程池源码分析_executors源码解析

线程池源码分析_executors源码解析概述在java中,线程池ThreadPoolExecutor是一个绕不过去的类,它是享元模式思想的体现,通过在容器中创建一定数量的线程加以重复利用,从而避免频繁创建线程带来的额外开销。一个设

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

概述

在 java 中,线程池 ThreadPoolExecutor 是一个绕不过去的类,它是享元模式思想的体现,通过在容器中创建一定数量的线程加以重复利用,从而避免频繁创建线程带来的额外开销。一个设置合理的线程池可以提高任务响应的速度,并且避免线程数超过硬件能力带来的意外情况。

在本文,将深入线程池源码,了解线程池的底层实现与运行机制。

一、构造方法

ThreadPoolExecutor 类一共提供了四个构造方法,我们基于参数最完整构造方法了解一下线程池创建所需要的变量:

public ThreadPoolExecutor(int corePoolSize, // 核心线程数
                          int maximumPoolSize, // 最大线程数
                          long keepAliveTime, // 非核心线程闲置存活时间
                          TimeUnit unit, // 时间单位
                          BlockingQueue<Runnable> workQueue, // 工作队列
                          ThreadFactory threadFactory, // 创建线程使用的线程工厂
                          RejectedExecutionHandler handler // 拒绝策略) {
}
  • 核心线程数:即长期存在的线程数,当线程池中运行线程未达到核心线程数时会优先创建新线程;
  • 最大线程数:当核心线程已满,工作队列已满,同时线程池中线程总数未超过最大线程数,会创建非核心线程;
  • 非核心线程闲置存活时间:当非核心线程闲置的时的最大存活时间;
  • 时间单位:非核心线程闲置存活时间的时间单位;
  • 任务队列:当核心线程满后,任务会优先加入工作队列,等等待核心线程消费;
  • 线程工厂:线程池创建新线程时使用的线程工厂;
  • 拒绝策略:当工作队列与线程池都满时,用于执行的策略;

二、线程池状态

1.线程池状态

线程池拥有一个 AtomicInteger 类型的成员变量 ctl ,通过位运算分别使用 ctl 的高位低位以便在一个值中存储线程数量以及线程池状态。

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 29(32-3)
private static final int COUNT_BITS = Integer.SIZE - 3;
// 允许的最大工作线程(2^29-1 约5亿)
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// 运行状态。线程池接受并处理新任务
private static final int RUNNING    = -1 << COUNT_BITS;
// 关闭状态。线程池不能接受新任务,处理完剩余任务后关闭。调用shutdown()方法会进入该状态。
private static final int SHUTDOWN   =  0 << COUNT_BITS;
// 停止状态。线程池不能接受新任务,并且尝试中断旧任务。调用shutdownNow()方法会进入该状态。
private static final int STOP       =  1 << COUNT_BITS;
// 整理状态。由关闭状态转变,线程池任务队列为空时进入该状态,会调用terminated()方法。
private static final int TIDYING    =  2 << COUNT_BITS;
// 终止状态。terminated()方法执行完毕后进入该状态,线程池彻底停止。
private static final int TERMINATED =  3 << COUNT_BITS;

2.线程状态的计算

这里比较不好理解的是上述-1的位运算,下面我们来分析一下:

在计算机中,二进制负数一般用补码表示,即源码取反再加一。但又有这种说法,即将最高位作为符号位,0为正数,1为负数。实际上两者是可以结合在一起看的。假如数字是单字节数,1 字节对应8 bit,即八位,现在,我们要计算 – 1。

按照第二种说法,最高位为符号位,则有 1/000 0001,然后按第一种说法取反后+1,并且符号位不变,则有 1/111 1110 + 1,即 1/111 1111。

现在回到 -1 << COUNT_BITS这行代码:

一个 int 是 4 个字节,对应 32 bit,按上述过程 -1 转为二进制即为 1/111……1111(32个1), COUNT_BITS是 29,-1 左移 29 位,最终得到 111.0…0000。

同理,计算其他的几种状态,可知分别是:

状态 二进制
RUNNING 111…0….00
SHUTDOWN 000…0….00
STOP 001…0….00
TIDYING 010…0….00
TERMINATED 011…0….00

其中,我们可以知道 SHUTDOWN 状态转为十进制也是 0 ,而 RUNNING 作为有符号数,它的最高位是 1,说明转为十进制以后是个负数,其他的状态最高位都是 0,转为十进制之后都是正数,也就是说,我们可以这么认为:

小于 SHUTDOWN 的就是 RUNNING,大于 SHUTDOWN 就是停止或者停止中。

这也是后面状态计算的一些写法的基础。比如 isRunning()方法:

private static boolean isRunning(int c) {
    return c < SHUTDOWN;
}

3.线程状态与工作线程数的获取

// 根据当前运行状态和工作线程数获取当前的 ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }
// 获取运行状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
// 获取工作线程数
private static int workerCountOf(int c)  { return c & CAPACITY; }

前面获取状态的时候调用了 ctlOf()方法,根据前面,我们可以知道,CAPACITY实际上是 29 位,而线程状态用的是 32 – 30 共 3 位,也就是说,ctl 共 32 位,高3 位用于表示线程池状态,而低 29 位表示工作线程的数量

这样上述三个方法就很好理解了:

  • ctlOf():获取 ctl。

    将工作线程数量与运行状态进行于运算,假如我们处于 RUNNING,并且有 1 个工作线程,那么 ctl = 111….000 | 000…. 001,最终得到 111 ….. 001;

  • runStateOf():获取运行状态。

    继续根据上文的数据,~CAPACITY 取反即为 111….000,与运行状态 111…0000 与运算,最终得到 111….000,相当于低位掩码,消去低 29 位;

  • workerCountOf():获取工作线程数。

    同理,c & CAPACITY里的 CAPACITY 相当于高位掩码,用于消去高 3 位,最终得到 00…001,即工作线程数。

同理,如果要增加工作线程数,就直接通过 CAS 去递增 ctl,比如新建线程中使用的公共方法:

private boolean compareAndIncrementWorkerCount(int expect) {
    // 通过 CAS 递增 ctl
    return ctl.compareAndSet(expect, expect + 1);
}

要改变线程池状态,就根据当前工作线程和要改变的状态去合成新的 ctl,然后 CAS 改变 ctl,比如 shutdown()中涉及的相关代码:

private void advanceRunState(int targetState) {
        for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||       
		        // 通过 CAS 改变 ctl
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

三、任务的创建与执行

线程池任务提交方法是 execute(),根据代码可知,当一个任务进来时,分四种情况:

  • 当前工作线程数小于核心线程数,启动新线程;
  • 当前工作线程数大于核心线程数,但是未大于最大线程数,尝试添加到工作队列;
  • 当前线程池核心线程和队列都满了,尝试创建新非核心线程。
  • 非核心线程创建失败,说明线程池彻底满了,执行拒绝策略。
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    
    // 1.当前工作线程数小于核心线程数,启动新线程
    if (workerCountOf(c) < corePoolSize) {
        // 添加任务
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    
    // 2. 当前工作线程数大于核心线程数,但是未大于最大线程数,尝试添加到工作队列
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 如果当前线程处于非运行态,并且移除当前任务成功,则拒绝任务(防止添加到一半就shutdown)
        if (! isRunning(recheck) && remove(command)) 
            reject(command);
        // 如果当前没有工作线程了,就启动新线程
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    
    // 3.当前线程池核心线程和队列都满了,尝试创建新非核心线程
    else if (!addWorker(command, false))
        // 4.线程池彻底满了,执行拒绝策略
        reject(command);
}

1.添加任务

添加任务依靠 addWorker()方法,这个方法很长,但是主要就干了两件事:

  • CAS 让 ctl 的工作线程数 +1;
  • 启动新的线程;
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    // 1.改变 ctl 使工作线程+1
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // 如果当前不处于运行状态,传入任务为空,并且任务队列为空的时候拒绝添加新任务
        // 即线程池 shutdown 时不让添加新任务,但是运行继续跑完任务队列里的任务。
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
            int wc = workerCountOf(c);
            // 线程不允许超过最大线程数,核心线程不允许超过最大核心线程数
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            // CAS 递增工作线程数
            if (compareAndIncrementWorkerCount(c))
                // 失败了就重新回到上面的retry处继续往下执行
                break retry;
            // 更新 ctl
            c = ctl.get();
            // 如果运行状态改变了就全部从来
            if (runStateOf(c) != rs)
                continue retry;
        }
    }

    // 2.启动新线程
    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
        // 创建新线程
        w = new Worker(firstTask);
        final Thread t = w.thread;
        if (t != null) {
            // 加锁
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                int rs = runStateOf(ctl.get());
			   
                // 如果线程池处于运行状态,或者没有新任务的SHUTDOWN状态(即SHUTDOW以后还在消费工作队列里的任务) 
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    // 线程是否在未启动前就已经启动了
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    workers.add(w);
                    int s = workers.size();
                     // 如果集合中的工作线程数大于最大线程数,则将池中最大线程数改为当前工作线程数
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    // 线程创建完成
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            // 如果线程成功创建,就启动线程,并且更改启动状态为成功
            if (workerAdded) {
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        // 如果线程启动不成功,就执行失败策略
        if (! workerStarted)
            // 启动失败策略,从当前工作线程队列移除当前启动失败的线程,递减工作线程数,然后尝试关闭线程池(如果当前任务就是线程池最后一个任务)
            addWorkerFailed(w);
    }
    return workerStarted;
}

2. 任务对象Worker

根据上文,不难发现,在线程池中线程往往以 Worker 对象的方式存在,那么这个 Worker 又是何方神圣?

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {

        // 工作线程
        final Thread thread;
    
        // 要执行的任务
        Runnable firstTask;
    
        // 线程执行过的任务数
        volatile long completedTasks;

        // 通过线程工厂创建工作线程
        Worker(Runnable firstTask) {
            setState(-1);
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

        // 执行任务
        public void run() {
            runWorker(this);
        }
    
    	... ...
    }

这个 Worker 类继承了 AQS,也就是说,他本身就相当于一个同步队列,结合他的成员变量 thread 和 firstTask,可以知道他实际上就是我们线程池中所说的“线程”。除了父类 AQS 本身提供的独占锁以外,Worker 还提供了一些检查任务线程运行状态以及中断线程相关的方法。

此外,线程池中还有一个工作队列 workers,用于保存当前全部的 Worker

private final HashSet<Worker> workers = new HashSet<Worker>();

3.任务的启动

当调用 Worker.run()的时候,其实调用的是 runWorker()方法。

runWorker()方法实际上就是调用线程执行任务的方法,他的逻辑大题是这样的:

  • 拿到入参的新 Worker,一直循环获取 Worker 里的任务;
  • 加锁然后执行任务;
  • 如果执行完任务流程,并且没有发生异常导致 Worker 挂掉,就直接复用 Worker(在获取任务的方法 getTask()中循环等待任务);
  • 如果执行完任务流程后发现发生异常导致 Worker 挂掉,就从工作队列中移除当前 Worker,并且补充一个新的;

如果整个流程执行完毕,就删除当前的 Worker。

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // 新创建的Worker默认state为-1,AQS的unlock方法会将其改为0,此后允许使用interruptIfStarted()方法进行中断
    
    // 完成任务以后是否需要移除当前Worker,即当前任务是否意外退出
    boolean completedAbruptly = true;
    
    try {
        // 循环获取任务
        while (task != null || (task = getTask()) != null) {
            // 加锁,防止 shundown 时中断正在运行的任务
            w.lock();
            // 如果线程池状态为 STOP 或更后面的状态,中断线程任务
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                // 钩子方法,默认空实现,需要自己提供
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    // 执行任务
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    // 钩子方法
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                // 任务执行完毕
                w.completedTasks++;
                w.unlock();
            }
        }
        
        completedAbruptly = false;
    } finally {
        // 根据completedAbruptly决定是否要移除意外退出的Worker,并补充新的Worker
        // 也就是说,如果上述过程顺利完成,工作线程没有挂掉,就不删除,下次继续用,否则就干掉它再补充一个。
        processWorkerExit(w, completedAbruptly);
    }
}

4.任务的获取与超时处理

runWorker()方法中,通过 getTask()方法去获取任务。值得注意的是,超时处理也在此处,简单的来说,整套流程是这样的:

  • 判断线程池是否关闭,工作队列是否为空,如果是说明没任务了,直接返回null,否则接着往下判断;
  • 判断当前是否存在非核心线程,如果是说明需要进行超时处理;
  • 获取任务,如果不需要超时处理,则直接从任务队列获取任务,否则根据 keepaliveTime 阻塞一段时间后获取任务,如果获取不到,说明非核心线程超时,返回 null 交给 runWorker()中的processWorkerExit()方法去删除;

换句话说,runWorker()方法一旦执行完毕,必然会删除当前的 Worker,而通过 getTask()拿任务的 Worker,在线程池正常运行的状态下,核心线程只会一直在 for 循环中等待直到拿到任务,而非核心线程超时以后拿不到任务就会返回一个 null,然后回到 runWorker()中走完processWorkerExit()方法被删除。

private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?

    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        // 如果线程池关闭了,并且工作队列里的任务都完成了,或者线程池直接进入了 STOP 或更进一步的状态,就不返回新任务
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        // 获取当前工作线程
        int wc = workerCountOf(c);

        // 核心线程是否超时(默认false)或当前是否存在非核心线程,即判断当前当前是否需要进行超时控制
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

        // 判断线程是否超过最大线程数或存在非核心线程
        if ((wc > maximumPoolSize || (timed && timedOut))
            // 并且除非任务队列为空,否则池中最少有一个线程
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            // 获取任务
            Runnable r = timed ?
                // 阻塞 keepaliveTime 以获取任务,如果在 keepaliveTime 时间内没有获取到任务,则返回 null.
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            // 如果获取不到任务,说明非核心线程超时了,下一轮判断确认是否退出循环。
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

四、线程池的中断

image-20210211171605477

线程池的中断方法分为三种:

  • shutdown():中断线程池,不再添加新任务,同时等待当前进行和队列中的任务完成
  • shutdownNow():立即中断线程池,不再添加新任务,同时中断所有工作中的任务,不再处理任务队列中任务

1.shutdown

shutdown 是有序关闭。主要干了三件事:

  • 改变当前线程池状态为 SHUTDOWN;
  • 将当前工作队列中的全部线程标记为中断;
  • 完成上述过程后将线程池状态改为 TIDYING
public void shutdown() {
    final ReentrantLock mainLock = this.mainLock;
    // 加锁
    mainLock.lock();
    try {
        checkShutdownAccess();
        // 改变当前线程池状态
        advanceRunState(SHUTDOWN);
        // 中断当前线程
        interruptIdleWorkers();
        // 钩子函数,默认空实现
        onShutdown(); // hook for ScheduledThreadPoolExecutor
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
}

其中,interruptIdleWorkers()方法如下:

private void interruptIdleWorkers(boolean onlyOne) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // 遍历工作队列中的全部 Worker
        for (Worker w : workers) {
            Thread t = w.thread;
            if (!t.isInterrupted() && w.tryLock()) {
                try {
                    // 标记为中断
                    t.interrupt();
                } catch (SecurityException ignore) {
                } finally {
                    w.unlock();
                }
            }
            if (onlyOne)
                break;
        }
    } finally {
        mainLock.unlock();
    }
}

2.shutdownNow

shutdownNow()shutdown()流程类似,但是会直接将状态转为 STOP,在 addWorker() 或者getTask()等处理任务的相关方法里,会针对 STOP 或更进一步的状态做区分,将不会再处理任务队列中的任务,配合drainQueue()方法以删除任务队列中的任务。

public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        // 改变当前线程池状态
        advanceRunState(STOP);
        // 中断当前线程
        interruptWorkers();
        // 删除任务队列中的任务
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}

五、拒绝策略

当任务队列已满,并且线程池中线程也到达最大线程数的时候,就会调用拒绝策略。也就是reject()方法

final void reject(Runnable command) {
    handler.rejectedExecution(command, this);
}

拒绝策略共分四种:

  • AbortPolicy:拒绝策略,直接抛出异常,默认策略;
  • CallerRunsPolicy:调用者运行策略,用调用者所在的线程来执行任务;
  • DiscardOldestPolicy:弃老策略,无声无息的丢弃阻塞队列中靠最前的任务,并执行当前任务;
  • DiscardPolicy:丢弃策略,直接无声无息的丢弃任务;

我们可以简单的了解一下他们的实现:

AbortPolicy

throw new RejectedExecutionException("Task " + r.toString() +
                                     " rejected from " +
                                     e.toString());

CallerRunsPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        r.run();
    }
}

DiscardOldestPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        // 弹出队头元素
        e.getQueue().poll();
        e.execute(r);
    }
}

DiscardPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
	// Does nothing
}

六、线程池的钩子函数

和 HashMap 与 LinkedHashMap 中的行为有点类似,在线程池的代码中,有些方法调用了一些具有空实现的方法,这些方法是提供给用户去继承并重写的钩子函数,主要包括三个:

  • beforeExecute():在执行任务之前回调
  • afterExecute():在任务执行完后回调
  • terminated():在线程池中的所有任务执行完毕后回调

通过继承 ThreadPoolExecutor 类,并重写以上三个方法,我们可以进行监控或者输出日志,更方便的了解线程池的状态。

值得一提的是,afterExecute()方法的入参类型是(Runnable r, Throwable t),也就是说,如果线程运行中抛出异常,我们也可以通过该方法去捕获异常并作出相应的处理。

七、总结

线程池提供了四个构造方法,参数最全的构造方法参数按顺序有:核心线程数,最大线程数,非核心线程闲置存活时间,存活时间单位,任务队列,线程工厂,拒绝策略。

线程池共有五种状态,分别是:RUNNING,SHUTDOWN,STOP,TYDYING,TERMINATED,它们与工作线程数量一同记录在成员变量 ctl 中,其中高 3 位用于记录状态,低 29 位用于记录工作线程数,实际使用中通过位运算去获取。

线程池中任务线程以继承了 AQS 的 Worker 类的实例形式存在。当添加任务时,会有四种情况:核心线程不满,优先创建核心线程;核心线程满,优先添加任务队列;核心线程与队列都满,创建非核心线程;线程和队列都满,则执行拒绝策略。

其中,拒绝策略分为四类,默认的拒绝策略 AbortPolicy;调用者运行策略 CallerRunsPolicy;弃老策略 DiscardOldestPolicy;丢弃策略 DiscardPolicy。

线程池的中断有两个方法:shutdown()shutdownNow(),两者都会让线程池不再接受新任务,但是 shutdown()会等待当前与任务队列中的任务执行完毕,而 shutdownNow()会直接中断当前任务,忽略并删除任务队列中的任务。

线程池提供了beforeExecute()afterExecute()terminated()三个钩子函数,其中,afterExecute()的入参含有抛出的异常,因此可以借由该方法处理线程池中线程抛出的异常。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170770.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • javascript nextSibling属性「建议收藏」

    javascript nextSibling属性「建议收藏」对于nextSibling属性,在W3school中的定义为:nextSibling属性返回指定节点之后紧跟的节点,在相同的树层级中。注意所返回的节点必须是与上一个节点是同级关系,且彼此之间不能有空格,否则将会返回:undefinedTitl</p> </div> <div class="item-meta"> <div class="item-meta-li author"> <a data-user="1" target="_blank" href="https://javaforall.net/user-2/1" class="avatar j-user-card"> <img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-60 photo' height='60' width='60' /> <span>全栈程序员-站长</span> </a> </div> <span class="item-meta-li date">2022年7月13日</span> <div class="item-meta-right"> <span class="item-meta-li views" title="阅读数"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-eye"></use></svg></i>344</span> </div> </div> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/161155.html" title="搜索引擎的工作原理" target="_blank" rel="bookmark"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="搜索引擎的工作原理"> </a> </div> <div class="item-content"> <h3 class="item-title"> <a href="https://javaforall.net/161155.html" target="_blank" rel="bookmark"> 搜索引擎的工作原理 </a> </h3> <div class="item-excerpt"> <p>搜索引擎的工作原理搜索引擎的基本工作原理包括如下三个过程:首先在互联网中发现、搜集网页信息;同时对信息进行提取和组织建立索引库;再由检索器根据用户输入的查询关键字,在索引库中快速检出文档,进行文档与查询的相关度评价,对将要输出的结果进行排序,并将查询结果返回给用户。1、抓取网页。每个独立的搜索引擎都有自己的网页抓取程序爬虫(spider)。爬虫Spider顺着网页中的超链接,从这个网站爬到另一个网站,通过超链接…</p> </div> <div class="item-meta"> <div class="item-meta-li author"> <a data-user="1" target="_blank" href="https://javaforall.net/user-2/1" class="avatar j-user-card"> <img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-60 photo' height='60' width='60' /> <span>全栈程序员-站长</span> </a> </div> <span class="item-meta-li date">2022年7月18日</span> <div class="item-meta-right"> <span class="item-meta-li views" title="阅读数"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-eye"></use></svg></i>21</span> </div> </div> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/122935.html" title="jetbrains golang 2021 激活码【永久激活】[通俗易懂]" target="_blank" rel="bookmark"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="jetbrains golang 2021 激活码【永久激活】[通俗易懂]"> </a> <a class="item-category" href="https://javaforall.net/category/%e5%bc%80%e5%8f%91%e5%b7%a5%e5%85%b7/idea" target="_blank">idea</a> </div> <div class="item-content"> <h3 class="item-title"> <a href="https://javaforall.net/122935.html" target="_blank" rel="bookmark"> jetbrains golang 2021 激活码【永久激活】[通俗易懂] </a> </h3> <div class="item-excerpt"> <p>(jetbrains golang 2021 激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~ML…</p> </div> <div class="item-meta"> <div class="item-meta-li author"> <a data-user="1" target="_blank" href="https://javaforall.net/user-2/1" class="avatar j-user-card"> <img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-60 photo' height='60' width='60' /> <span>全栈程序员-站长</span> </a> </div> <span class="item-meta-li date">2022年3月21日</span> <div class="item-meta-right"> <span class="item-meta-li views" title="阅读数"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-eye"></use></svg></i>340</span> </div> </div> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/169707.html" title="tcp 粘包[通俗易懂]" target="_blank" rel="bookmark"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="tcp 粘包[通俗易懂]"> </a> </div> <div class="item-content"> <h3 class="item-title"> <a href="https://javaforall.net/169707.html" target="_blank" rel="bookmark"> tcp 粘包[通俗易懂] </a> </h3> <div class="item-excerpt"> <p>tcp 粘包[通俗易懂]tcp粘包</p> </div> <div class="item-meta"> <div class="item-meta-li author"> <a data-user="1" target="_blank" href="https://javaforall.net/user-2/1" class="avatar j-user-card"> <img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-60 photo' height='60' width='60' /> <span>全栈程序员-站长</span> </a> </div> <span class="item-meta-li date">2022年8月11日</span> <div class="item-meta-right"> <span class="item-meta-li views" title="阅读数"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-eye"></use></svg></i>6</span> </div> </div> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/144108.html" title="Android应用开发揭秘11" target="_blank" rel="bookmark"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="Android应用开发揭秘11"> </a> </div> <div class="item-content"> <h3 class="item-title"> <a href="https://javaforall.net/144108.html" target="_blank" rel="bookmark"> Android应用开发揭秘11 </a> </h3> <div class="item-excerpt"> <p>Android应用开发揭秘11Android应用开发揭秘11</p> </div> <div class="item-meta"> <div class="item-meta-li author"> <a data-user="1" target="_blank" href="https://javaforall.net/user-2/1" class="avatar j-user-card"> <img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-60 photo' height='60' width='60' /> <span>全栈程序员-站长</span> </a> </div> <span class="item-meta-li date">2022年5月20日</span> <div class="item-meta-right"> <span class="item-meta-li views" title="阅读数"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-eye"></use></svg></i>35</span> </div> </div> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/167883.html" title="什么是网站的灵魂_测试性能网站" target="_blank" rel="bookmark"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="什么是网站的灵魂_测试性能网站"> </a> </div> <div class="item-content"> <h3 class="item-title"> <a href="https://javaforall.net/167883.html" target="_blank" rel="bookmark"> 什么是网站的灵魂_测试性能网站 </a> </h3> <div class="item-excerpt"> <p>什么是网站的灵魂_测试性能网站前言在前一篇随笔《大型网站系统架构的演化》中,介绍了大型网站的演化过程,期间穿插了一些技术和手段,我们可以从中看出一个大型网站的轮廓,但想要掌握设计开发维护大型网站的技术,需要我们一步一步去研究实践</p> </div> <div class="item-meta"> <div class="item-meta-li author"> <a data-user="1" target="_blank" href="https://javaforall.net/user-2/1" class="avatar j-user-card"> <img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-60 photo' height='60' width='60' /> <span>全栈程序员-站长</span> </a> </div> <span class="item-meta-li date">2022年8月4日</span> <div class="item-meta-right"> <span class="item-meta-li views" title="阅读数"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-eye"></use></svg></i>5</span> </div> </div> </div> </li> </ul> </div> <div id="comments" class="entry-comments"> <div id="respond" class="comment-respond"> <h3 id="reply-title" class="comment-reply-title">发表回复</h3><form action="https://javaforall.net/wp-comments-post.php" method="post" id="commentform" class="comment-form"><p class="comment-notes"><span id="email-notes">您的邮箱地址不会被公开。</span> <span class="required-field-message">必填项已用 <span class="required">*</span> 标注</span></p><div class="comment-form-comment"><textarea autocomplete="new-password" id="j265fd99e5" name="j265fd99e5" class="required" rows="4" placeholder="写下你的评论…"></textarea><textarea id="comment" aria-label="hp-comment" aria-hidden="true" name="comment" autocomplete="new-password" style="padding:0 !important;clip:rect(1px, 1px, 1px, 1px) !important;position:absolute !important;white-space:nowrap !important;height:1px !important;width:1px !important;overflow:hidden !important;" tabindex="-1"></textarea><script data-noptimize>document.getElementById("comment").setAttribute( "id", "a456e2c6236a13ed4d9743ebf72f1665" );document.getElementById("j265fd99e5").setAttribute( "id", "comment" );</script><div class="comment-form-smile j-smilies" data-target="#comment"><i class="wpcom-icon wi smile-icon"><svg aria-hidden="true"><use xlink:href="#wi-emotion"></use></svg></i></div></div><div class="comment-form-author"><label for="author">昵称:</label><input id="author" name="author" type="text" value="" size="30"></div> <div class="comment-form-email"><label for="email">邮箱:</label><input id="email" name="email" type="text" value=""></div> <div class="comment-form-url"><label for="url">网址:</label><input id="url" name="url" type="text" value="" size="30"></div> <label class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"> 记住昵称、邮箱和网址,下次评论免输入</label> <div class="form-submit"><button name="submit" type="submit" id="submit" class="wpcom-btn btn-primary btn-xs submit">提交</button> <input type='hidden' name='comment_post_ID' value='170770' id='comment_post_ID' /> <input type='hidden' name='comment_parent' id='comment_parent' value='0' /> </div></form> </div><!-- #respond --> </div><!-- .comments-area --> </article> </main> <aside class="sidebar"> <div class="widget widget_profile"><div class="profile-cover"><img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450.jpg" data-original="//javaforall.net/wp-content/uploads/2025/04/anthony-delanoix-urUdKCxsTUI-unsplash-1.webp" alt="全栈程序员-站长"></div> <div class="avatar-wrap"> <a target="_blank" href="https://javaforall.net/user-2/1" class="avatar-link"><img alt='全栈程序员-站长的头像' src='https://javaforall.net/wp-content/uploads/2025/04/2025042212521933-300x300.jpg' class='avatar avatar-120 photo' height='120' width='120' /></a></div> <div class="profile-info"> <a target="_blank" href="https://javaforall.net/user-2/1" class="profile-name"><span class="author-name">全栈程序员-站长</span></a> <p class="author-description">本网站汇聚当前互联网主流语音,持续更新,欢迎关注公众号“全栈程序员社区”</p> <div class="profile-stats"> <div class="profile-stats-inner"> <div class="user-stats-item"> <b>95.5K</b> <span>文章</span> </div> <div class="user-stats-item"> <b>2</b> <span>粉丝</span> </div> </div> </div> <button type="button" class="wpcom-btn btn-xs btn-follow j-follow btn-primary" data-user="1"><i class="wpcom-icon wi"><svg aria-hidden="true"><use xlink:href="#wi-add"></use></svg></i>关注</button> </div> <div class="profile-posts"> <h3 class="widget-title"><span>最近文章</span></h3> <ul> <li><a href="https://javaforall.net/192368.html" title="缺陷报告-模板_质量缺陷报告">缺陷报告-模板_质量缺陷报告</a></li> <li><a href="https://javaforall.net/192369.html" title="Ubuntu如何安装vscode_ubuntu20.0.4 vscode配置c++环境">Ubuntu如何安装vscode_ubuntu20.0.4 vscode配置c++环境</a></li> <li><a href="https://javaforall.net/192370.html" title="C++之vector 初始化指定大小容量[通俗易懂]">C++之vector 初始化指定大小容量[通俗易懂]</a></li> <li><a href="https://javaforall.net/192371.html" title="linux命令行修改用户名_linux 更改用户密码">linux命令行修改用户名_linux 更改用户密码</a></li> <li><a href="https://javaforall.net/192372.html" title="CountDownTimer_final countdown">CountDownTimer_final countdown</a></li> <li><a href="https://javaforall.net/192373.html" title="mysql 练习题及答案 50道">mysql 练习题及答案 50道</a></li> <li><a href="https://javaforall.net/192374.html" title="京东云服务器_docker 京东自动签到">京东云服务器_docker 京东自动签到</a></li> <li><a href="https://javaforall.net/192375.html" title="U盘中毒了?教你如何删除System Volume Information这个顽固文件夹「建议收藏」">U盘中毒了?教你如何删除System Volume Information这个顽固文件夹「建议收藏」</a></li> <li><a href="https://javaforall.net/231391.html" title="Web Services 教程">Web Services 教程</a></li> <li><a href="https://javaforall.net/192376.html" title="从0到1搭建一款数据平台产品_全国大数据采集软件免费">从0到1搭建一款数据平台产品_全国大数据采集软件免费</a></li> </ul> </div> </div><div class="widget widget_post_thumb"><h3 class="widget-title"><span>最新发布</span></h3> <ul> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/192442.html" title="idea如何配置数据库连接_idea配置数据库驱动"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="idea如何配置数据库连接_idea配置数据库驱动"> </a> </div> <div class="item-content"> <p class="item-title"><a href="https://javaforall.net/192442.html" title="idea如何配置数据库连接_idea配置数据库驱动">idea如何配置数据库连接_idea配置数据库驱动</a></p> <p class="item-date">2025年12月15日</p> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/192457.html" title="idea配置Tomcat_tomcat docbase"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="idea配置Tomcat_tomcat docbase"> </a> </div> <div class="item-content"> <p class="item-title"><a href="https://javaforall.net/192457.html" title="idea配置Tomcat_tomcat docbase">idea配置Tomcat_tomcat docbase</a></p> <p class="item-date">2025年12月14日</p> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/192733.html" title="idea创建一个javaweb项目"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="idea创建一个javaweb项目"> </a> </div> <div class="item-content"> <p class="item-title"><a href="https://javaforall.net/192733.html" title="idea创建一个javaweb项目">idea创建一个javaweb项目</a></p> <p class="item-date">2025年12月9日</p> </div> </li> <li class="item"> <div class="item-img"> <a class="item-img-inner" href="https://javaforall.net/192761.html" title="idea社区版免费吗_intellij idea community edition"> <img class="j-lazy" src="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" data-original="https://javaforall.net/wp-content/uploads/2020/11/2020110817443450-480x300.jpg" width="480" height="300" alt="idea社区版免费吗_intellij idea community edition"> </a> </div> <div class="item-content"> <p class="item-title"><a href="https://javaforall.net/192761.html" title="idea社区版免费吗_intellij idea community edition">idea社区版免费吗_intellij idea community edition</a></p> <p class="item-date">2025年12月8日</p> </div> </li> </ul> </div> </aside> </div> </div> <footer class="footer"> <div class="container"> <div class="footer-col-wrap footer-with-logo-icon"> <div class="footer-col footer-col-logo"> <img src="http://javaforall.net/wp-content/uploads/2020/10/4545-头像.jpg" alt="全栈程序员必看"> </div> <div class="footer-col footer-col-copy"> <ul class="footer-nav hidden-xs"><li id="menu-item-152" class="menu-item menu-item-152"><a href="https://javaforall.net/contact">联系我们</a></li> </ul> <div class="copyright"> <p>Copyright ©2018-2025 版权所有 <a href="http://beian.miit.gov.cn" target="_blank" rel="nofollow noopener noreferrer">晋ICP备19011774号</a> Powered by 全栈程序员必看 <a href="/sitemap.xml" target="_blank" rel="noopener">网站地图</a></p> </div> </div> <div class="footer-col footer-col-sns"> <div class="footer-sns"> <a class="sns-wx" href="javascript:;" aria-label="icon"> <i class="wpcom-icon fa fa-wechat sns-icon"></i> <span style="background-image:url('//javaforall.net/wp-content/uploads/2020/11/2020110814274114.jpg');"></span> </a> </div> </div> </div> </div> </footer> <div class="action action-style-0 action-color-1 action-pos-0" style="bottom:15%;"> <div class="action-item"> <i class="wpcom-icon fa fa-wechat action-item-icon"></i> <div class="action-item-inner action-item-type-1"> <img class="action-item-img" src="http://javaforall.net/wp-content/uploads/2020/11/2020110814274114.jpg" alt="关注全栈程序员社区公众号"> </div> </div> <div class="action-item gotop j-top"> <i class="wpcom-icon wi action-item-icon"><svg aria-hidden="true"><use xlink:href="#wi-arrow-up-2"></use></svg></i> </div> </div> <script type="speculationrules"> {"prefetch":[{"source":"document","where":{"and":[{"href_matches":"\/*"},{"not":{"href_matches":["\/wp-*.php","\/wp-admin\/*","\/wp-content\/uploads\/*","\/wp-content\/*","\/wp-content\/plugins\/*","\/wp-content\/themes\/justnews\/*","\/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} </script> <script type="text/javascript" id="main-js-extra"> /* <![CDATA[ */ var _wpcom_js = {"webp":"","ajaxurl":"https:\/\/javaforall.net\/wp-admin\/admin-ajax.php","theme_url":"https:\/\/javaforall.net\/wp-content\/themes\/justnews","slide_speed":"5000","is_admin":"0","lang":"zh_CN","js_lang":{"share_to":"\u5206\u4eab\u5230:","copy_done":"\u590d\u5236\u6210\u529f\uff01","copy_fail":"\u6d4f\u89c8\u5668\u6682\u4e0d\u652f\u6301\u62f7\u8d1d\u529f\u80fd","confirm":"\u786e\u5b9a","qrcode":"\u4e8c\u7ef4\u7801","page_loaded":"\u5df2\u7ecf\u5230\u5e95\u4e86","no_content":"\u6682\u65e0\u5185\u5bb9","load_failed":"\u52a0\u8f7d\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\uff01","expand_more":"\u9605\u8bfb\u5269\u4f59 %s"},"lightbox":"1","post_id":"170770","user_card_height":"356","poster":{"notice":"\u8bf7\u300c\u70b9\u51fb\u4e0b\u8f7d\u300d\u6216\u300c\u957f\u6309\u4fdd\u5b58\u56fe\u7247\u300d\u540e\u5206\u4eab\u7ed9\u66f4\u591a\u597d\u53cb","generating":"\u6b63\u5728\u751f\u6210\u6d77\u62a5\u56fe\u7247...","failed":"\u6d77\u62a5\u56fe\u7247\u751f\u6210\u5931\u8d25"},"video_height":"482","fixed_sidebar":"1","dark_style":"0","font_url":"\/\/fonts.proxy.ustclug.org\/css2?family=Noto+Sans+SC:wght@400;500&display=swap","follow_btn":"<i class=\"wpcom-icon wi\"><svg aria-hidden=\"true\"><use xlink:href=\"#wi-add\"><\/use><\/svg><\/i>\u5173\u6ce8","followed_btn":"\u5df2\u5173\u6ce8","user_card":"1"}; /* ]]> */ </script> <script type="text/javascript" src="https://javaforall.net/wp-content/themes/justnews/js/main.js?ver=6.20.0" id="main-js"></script> <script type="text/javascript" src="https://javaforall.net/wp-content/themes/justnews/themer/assets/js/icons-2.8.9.js?ver=2.8.9" id="wpcom-icons-js"></script> <script type="text/javascript" id="wp-postviews-cache-js-extra"> /* <![CDATA[ */ var viewsCacheL10n = {"admin_ajax_url":"https:\/\/javaforall.net\/wp-admin\/admin-ajax.php","nonce":"b842d24635","post_id":"170770"}; /* ]]> */ </script> <script type="text/javascript" src="https://javaforall.net/wp-content/plugins/wp-postviews/postviews-cache.js?ver=1.77" id="wp-postviews-cache-js"></script> <script type="text/javascript" id="wpcom-member-js-extra"> /* <![CDATA[ */ var _wpmx_js = {"ajaxurl":"https:\/\/javaforall.net\/wp-admin\/admin-ajax.php","plugin_url":"https:\/\/javaforall.net\/wp-content\/plugins\/wpcom-member\/","post_id":"170770","js_lang":{"login_desc":"\u60a8\u8fd8\u672a\u767b\u5f55\uff0c\u8bf7\u767b\u5f55\u540e\u518d\u8fdb\u884c\u76f8\u5173\u64cd\u4f5c\uff01","login_title":"\u8bf7\u767b\u5f55","login_btn":"\u767b\u5f55","reg_btn":"\u6ce8\u518c"},"login_url":"https:\/\/javaforall.net\/login?modal-type=login","register_url":"https:\/\/javaforall.net\/register?modal-type=register","errors":{"require":"\u4e0d\u80fd\u4e3a\u7a7a","email":"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u7535\u5b50\u90ae\u7bb1","pls_enter":"\u8bf7\u8f93\u5165","password":"\u5bc6\u7801\u5fc5\u987b\u4e3a6~32\u4e2a\u5b57\u7b26","passcheck":"\u4e24\u6b21\u5bc6\u7801\u8f93\u5165\u4e0d\u4e00\u81f4","phone":"\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u624b\u673a\u53f7\u7801","terms":"\u8bf7\u9605\u8bfb\u5e76\u540c\u610f\u6761\u6b3e","sms_code":"\u9a8c\u8bc1\u7801\u9519\u8bef","captcha_verify":"\u8bf7\u70b9\u51fb\u6309\u94ae\u8fdb\u884c\u9a8c\u8bc1","captcha_fail":"\u4eba\u673a\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5","nonce":"\u968f\u673a\u6570\u6821\u9a8c\u5931\u8d25","req_error":"\u8bf7\u6c42\u5931\u8d25"}}; /* ]]> */ </script> <script type="text/javascript" src="https://javaforall.net/wp-content/plugins/wpcom-member/js/index.js?ver=1.7.10" id="wpcom-member-js"></script> <script type="text/javascript" id="QAPress-js-js-extra"> /* <![CDATA[ */ var QAPress_js = {"ajaxurl":"https:\/\/javaforall.net\/wp-admin\/admin-ajax.php","ajaxloading":"https:\/\/javaforall.net\/wp-content\/plugins\/qapress\/images\/loading.gif","max_upload_size":"2097152","compress_img_size":"0","lang":{"delete":"\u5220\u9664","nocomment":"\u6682\u65e0\u56de\u590d","nocomment2":"\u6682\u65e0\u8bc4\u8bba","addcomment":"\u6211\u6765\u56de\u590d","submit":"\u53d1\u5e03","loading":"\u6b63\u5728\u52a0\u8f7d...","error1":"\u53c2\u6570\u9519\u8bef\uff0c\u8bf7\u91cd\u8bd5","error2":"\u8bf7\u6c42\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\uff01","confirm":"\u5220\u9664\u64cd\u4f5c\u65e0\u6cd5\u6062\u590d\uff0c\u5e76\u5c06\u540c\u65f6\u5220\u9664\u5f53\u524d\u56de\u590d\u7684\u8bc4\u8bba\u4fe1\u606f\uff0c\u60a8\u786e\u5b9a\u8981\u5220\u9664\u5417\uff1f","confirm2":"\u5220\u9664\u64cd\u4f5c\u65e0\u6cd5\u6062\u590d\uff0c\u60a8\u786e\u5b9a\u8981\u5220\u9664\u5417\uff1f","confirm3":"\u5220\u9664\u64cd\u4f5c\u65e0\u6cd5\u6062\u590d\uff0c\u5e76\u5c06\u540c\u65f6\u5220\u9664\u5f53\u524d\u95ee\u9898\u7684\u56de\u590d\u8bc4\u8bba\u4fe1\u606f\uff0c\u60a8\u786e\u5b9a\u8981\u5220\u9664\u5417\uff1f","deleting":"\u6b63\u5728\u5220\u9664...","success":"\u64cd\u4f5c\u6210\u529f\uff01","denied":"\u65e0\u64cd\u4f5c\u6743\u9650\uff01","error3":"\u64cd\u4f5c\u5f02\u5e38\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\uff01","empty":"\u5185\u5bb9\u4e0d\u80fd\u4e3a\u7a7a","submitting":"\u6b63\u5728\u63d0\u4ea4...","success2":"\u63d0\u4ea4\u6210\u529f\uff01","ncomment":"0\u6761\u8bc4\u8bba","login":"\u62b1\u6b49\uff0c\u60a8\u9700\u8981\u767b\u5f55\u624d\u80fd\u8fdb\u884c\u56de\u590d","error4":"\u63d0\u4ea4\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\uff01","need_title":"\u8bf7\u8f93\u5165\u6807\u9898","need_cat":"\u8bf7\u9009\u62e9\u5206\u7c7b","need_content":"\u8bf7\u8f93\u5165\u5185\u5bb9","success3":"\u66f4\u65b0\u6210\u529f\uff01","success4":"\u53d1\u5e03\u6210\u529f\uff01","need_all":"\u6807\u9898\u3001\u5206\u7c7b\u548c\u5185\u5bb9\u4e0d\u80fd\u4e3a\u7a7a","length":"\u5185\u5bb9\u957f\u5ea6\u4e0d\u80fd\u5c11\u4e8e10\u4e2a\u5b57\u7b26","load_done":"\u56de\u590d\u5df2\u7ecf\u5168\u90e8\u52a0\u8f7d","load_fail":"\u52a0\u8f7d\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\uff01","load_more":"\u70b9\u51fb\u52a0\u8f7d\u66f4\u591a","approve":"\u786e\u5b9a\u8981\u5c06\u5f53\u524d\u95ee\u9898\u8bbe\u7f6e\u4e3a\u5ba1\u6838\u901a\u8fc7\u5417\uff1f","end":"\u5df2\u7ecf\u5230\u5e95\u4e86","upload_fail":"\u56fe\u7247\u4e0a\u4f20\u51fa\u9519\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\uff01","file_types":"\u4ec5\u652f\u6301\u4e0a\u4f20jpg\u3001png\u3001gif\u683c\u5f0f\u7684\u56fe\u7247\u6587\u4ef6","file_size":"\u56fe\u7247\u5927\u5c0f\u4e0d\u80fd\u8d85\u8fc72M","uploading":"\u6b63\u5728\u4e0a\u4f20...","upload":"\u63d2\u5165\u56fe\u7247"}}; /* ]]> */ </script> <script type="text/javascript" src="https://javaforall.net/wp-content/plugins/qapress/js/qa.js?ver=4.10.2" id="QAPress-js-js"></script> <script type="text/javascript" src="https://javaforall.net/wp-content/themes/justnews/js/wp-embed.js?ver=6.20.0" id="wp-embed-js"></script> <script type="text/javascript" src="https://javaforall.net/wp-content/plugins/baidu-submit/assets/baidu_push.js" id="wb-baidu-push-js"></script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?2f4d2b9bcf94270f8bf99ccde97cb4b9"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "@id": "https://javaforall.net/170770.html", "url": "https://javaforall.net/170770.html", "headline": "线程池源码分析_executors源码解析", "image": "http://qn.javajgs.com/20220816/97f12ff0-c908-4d91-b003-1b22e464a40120220816a038d220-1342-43c8-8072-e1ec981ee1051.jpg", "description": "线程池源码分析_executors源码解析概述在java中,线程池ThreadPoolExecutor是一个绕不过去的类,它是享元模式思想的体现,通过在容器中创建一定数量的线程加以重复利用,从而避免频繁创建线程带来的额外开销。一个设", "datePublished": "2022-08-16T23:36:00+08:00", "dateModified": "2022-08-16T23:36:00+08:00", "author": {"@type":"Person","name":"全栈程序员-站长","url":"https://javaforall.net/user-2/1","image":"//javaforall.net/wp-content/uploads/2025/04/2025042212371781.jpeg"} } </script> </body> </html>