Java并发编程一线程池简介

Java并发编程一线程池简介

为什么我们需要使用线程池?

我们知道线程是一种比较昂贵的资源,我们通过程序每创建一个线程去执行,其实操作系统都会对应地创建一个线程去执行我们的任务,而我们频繁的创建、销毁线程是非常耗费系统资源的,当并发数不大时,对系统似乎没什么影响,但当并发数很大时,我们为每一个请求都去创建一个线程,然后等待被调度、执行完任务后再销毁,这样频繁的创建、销毁线程是很耗费系统资源的。

而我们使用线程池去管理线程,就可以很好的减少这种损耗,因为线程池会复用线程,什么是复用线程呢?就是线程池里面的线程,并不和我们自己创建一个线程去执行单个任务一样,执行完这个任务线程就结束了,而线程池中的线程,它的执行逻辑中有一个while循环,在这个while循环中,线程会不断的去获取任务,然后执行(有任务的情况下),如果在高并发环境下,这会极大的减少线程的创建与销毁操作,节约系统的资源。

我们来看一看线程池的部分源码:

    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                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 {
            processWorkerExit(w, completedAbruptly);
        }
    }

Repeatedly gets tasks from queue and executes them这是上面这个方法的一段注释,从方法的代码和注释中,都很明显的展现了线程池中的线程并不是执行完一个任务就结束了,而是会主动(重复)去获取任务,然后执行。

线程池的设计

很明显是面向接口编程。
在这里插入图片描述
线程池的一些属性

在这里插入图片描述
下面是这些属性的源码与注释,结合上图应该不难看懂。

    /**
     * Core pool size is the minimum number of workers to keep alive
     * (and not allow to time out etc) unless allowCoreThreadTimeOut
     * is set, in which case the minimum is zero.
     */
    private volatile int corePoolSize;
    /**
     * Maximum pool size. Note that the actual maximum is internally
     * bounded by CAPACITY.
     */
    private volatile int maximumPoolSize;
    /**
     * Timeout in nanoseconds for idle threads waiting for work.
     * Threads use this timeout when there are more than corePoolSize
     * present or if allowCoreThreadTimeOut. Otherwise they wait
     * forever for new work.
     */
    private volatile long keepAliveTime;
   /**
     * The queue used for holding tasks and handing off to worker
     * threads.  We do not require that workQueue.poll() returning
     * null necessarily means that workQueue.isEmpty(), so rely
     * solely on isEmpty to see if the queue is empty (which we must
     * do for example when deciding whether to transition from
     * SHUTDOWN to TIDYING).  This accommodates special-purpose
     * queues such as DelayQueues for which poll() is allowed to
     * return null even if it may later return non-null when delays
     * expire.
     */
    private final BlockingQueue<Runnable> workQueue;
    /**
     * Factory for new threads. All threads are created using this
     * factory (via method addWorker).  All callers must be prepared
     * for addWorker to fail, which may reflect a system or user's
     * policy limiting the number of threads.  Even though it is not
     * treated as an error, failure to create threads may result in
     * new tasks being rejected or existing ones remaining stuck in
     * the queue.
     *
     * We go further and preserve pool invariants even in the face of
     * errors such as OutOfMemoryError, that might be thrown while
     * trying to create threads.  Such errors are rather common due to
     * the need to allocate a native stack in Thread.start, and users
     * will want to perform clean pool shutdown to clean up.  There
     * will likely be enough memory available for the cleanup code to
     * complete without encountering yet another OutOfMemoryError.
     */
    private volatile ThreadFactory threadFactory;
    /**
     * Handler called when saturated or shutdown in execute.
     */
    private volatile RejectedExecutionHandler handler;

线程池结构
在这里插入图片描述
线程池创建线程

这个图是中文的,应该很生动了,就不需要解释了吧。
在这里插入图片描述

线程池拒绝任务

当线程池的任务队列满了,并且无法再创建新的线程了(线程数量达到maximumPoolSize),线程池就会拒绝任务。其实还有其他情况线程池也会拒绝任务,这里只是简单让大家知道,线程池是会拒绝任务的。
在这里插入图片描述

这里只是让大家对Java线程池有一个大概的了解,并没有详细讲解原理,毕竟博主也是初学者,以后有机会会再进行补充的。

发布了302 篇原创文章 · 获赞 435 · 访问量 71万+

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/104334254