`

线程池简单实现

 
阅读更多
以下实现注意,并没有用到最大线程数参数max
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

public class IndexDatasourceController {

    private static AtomicInteger taskCount = new AtomicInteger(0);

    private static Integer testint = 1;
    // 仓库,等待队列,所有线程会先入队,大于min数量线程的任务会先停留队中,但是如果超过了队列的容量,会生成新的线程执行任务,max参数是最多的线程数量,大于这个max不再创建线程执行策略
    private BlockingQueue<Runnable> taskQueue;

    // 工作线程,初始时是min个线程
    private List<Thread> workers;

    //工作标识
    private volatile boolean working = true;
    // 初始线程数,队列大小(在真实实现中大小定义在队列参数里)
    public IndexDatasourceController(int poolSize, int taskQueueSize) {
        // 仓库
        this.taskQueue = new LinkedBlockingDeque<>(taskQueueSize);
        // 初始化线程
        this.workers = Collections.synchronizedList(new ArrayList<>());
        // 线程数启动(传入3,启动3个线程),如果只有1个任务执行1个任务,不会影响线程池的使用。
        for (int i= 0; i<poolSize; i++) {
            Worker worker = new Worker(this);
            // 开启一个线程 并且运行run方法
            worker.start();
            this.workers.add(worker);
        }
    }

    // 放入任务方法到仓库
    public boolean submit(Runnable task) {
// 只要没有关闭,[b]0到max都到队列(这个理解有瑕疵)[/b],如果队列足够大,会一直放到队列里,如果超过队列大小,小于max,会开启新的线程,如果连max也超过了那么执行拒绝策略
        if(this.working) {
            // 无阻塞插入
// offer 如果有空闲任务队列刚好可以接收此任务,那么返回 true,否则返回 false
            this.taskQueue.offer(task);
        }
        return false;
    }

    // 关闭方法
// 不接受新的任务提交,但是会继续处理等待队列中的任务
    public void shutdown() {
        this.working = false;
        // 中断阻塞的线程
        for(Thread t : this.workers) {
            if (t.getState().equals(Thread.State.BLOCKED)
                    || t.getState().equals(Thread.State.WAITING)
                    || t.getState().equals(Thread.State.TIMED_WAITING)) {

                t.interrupt();
            }
        }
    }
    // 开启min个线程,每个处理完成,不断while去仓库队列领取任务
    private static class Worker extends Thread {

        IndexDatasourceController pool;
        public Worker(IndexDatasourceController pool) {
            super();
            this.pool = pool;
        }
        public void run() {

            // 如果是工作的,如果仓库还有任务,就跑完
            while (this.pool.working || this.pool.taskQueue.size()>0) {
                Runnable task = null;
                try{
                    // 当队列中有任务,池已关闭时
                    // 如果是工作状态,则阻塞
                    if(this.pool.working) {
                        // take阻塞删除
//取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止
                        task = this.pool.taskQueue.take();
                    }
                    //不是工作状态,不阻塞
                    else {
                        // poll直接删除,因为线程池已经关闭,不需要阻塞等待队列中的任务,没有任务直接结束
                        task = this.pool.taskQueue.poll();
                    }
                } catch (Exception e) {

                }

                if(task != null) {
                    // run同步执行任务
                    task.run();
                    taskCount.incrementAndGet();
                    System.out.println("执行了线程" + Thread.currentThread().getName() +"执行完,个数:"+ taskCount);
                }
            }
            System.out.println( Thread.currentThread().getName() + "结束");
        }
    }

    public static void main(String[] args) {
        //开启3个线程,阻塞队列取阻塞数据
        //第一个参数是核心线程数,第二个是队列的大小
        IndexDatasourceController pool = new IndexDatasourceController(3,6);
        for (int i=0; i<6 ;i++) {
            // 放入任务方法到仓库
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("任务开始执行:" + testint++);
                    try {
                        Thread.sleep(2000L);
                    } catch (Exception e) {

                    }
                }
            });
        }
        pool.shutdown();
    }
}


思想:实例化线程池ThreadPoolExecutor(corePoolSize核心线程数,
maximumPoolSize最大线程数,
workQueue任务队列,
keepAliveTime空闲线程的保活时间,对于没有执行的线程任务的线程如果超时就被关闭,这里对于小于核心线程数的线程不会超时
threadFactory用于生成线程,
handler采取策略:
如果失败,说明当前线程数已经达到 maximumPoolSize,执行拒绝策略
RUNNING 状态,那么移除已经入队的这个任务,并且执行拒绝策略
抛出异常,
直接忽略,
如果线程池没有关闭,直接只能此任务线程,
如果线程没有关闭,直接删除队列队头的任务,提交这个任务到等待队列中

开始最多创建核心线程数(n个)个线程,线程池执行过程中n个线程取任务队列,阻塞take()获取,所有任务实例化后不断submit线程到队列,队列被n个线程不断消费,直到消费结束。
如果队列也满了后,任务还有,这时才会去创建新的非核心线程(max),如果大于max数量线程,执行拒绝策略。

深入理解线程池:
https://javadoop.com/post/java-thread-pool

BlockingQueue深入分析:
https://blog.csdn.net/vernonzheng/article/details/8247564

当核心线程数满了后,任务优先进入等待队列。如果等待队列也满了后,才会去创建新的非核心线程 :
https://blog.csdn.net/firefile/article/details/80745627

结合了AQS说明,异常场景等说明的很到位的好文章:
https://www.cnblogs.com/trust-freedom/p/6681948.html#label_3_4
分享到:
评论

相关推荐

    易语言真正的线程池简易实现

    易语言简易线程池的实现。 ——V雪落有声V原创。转载请保留。前文:。为了能充分理解本篇文章的内容,需要了解的知识如下:。1.事件对象的使用:http://baike.baidu.com/view/751499.htm。2.信号量的使用:...

    一个简单线程池的实现

    在这个简单的线程池实现中,我们可以通过`pthread_pool.cpp`、`MainFunctionForTest.cpp`、`twork_work.cpp`、`pthread_pool.h`和`twork_work.h`这五个文件来理解其基本架构和工作原理。 首先,`pthread_pool.h`...

    线程池简单实现chenjiegui

    在Java中,线程池是通过`java.util.concurrent`包中的`ExecutorService`接口及其实现类来实现的,如`ThreadPoolExecutor`。下面我们将深入探讨线程池的工作原理、核心参数以及如何在实际开发中使用线程池。 线程池...

    c++11线程池简单实现

    本资源是基于C++11标准实现的一个简单的线程池,它利用了C++11的新特性,如`std::thread`,`std::function`,以及智能指针等。 首先,`std::thread`是C++11引入的用于创建和管理线程的类。通过创建`std::thread`...

    C++11 简易线程池实现

    简易的C++11线程池实现,线程池为固定方式,后面会新增非固定模式。

    简单C++线程池实现

    本文将深入探讨如何实现一个简单的线程池,并通过提供的文件名`_threadpool.cpp`, `_promain.cpp`, `_threadpool.h`来解释其核心概念和组件。 首先,`_threadpool.h`是头文件,通常包含类定义和相关函数声明。...

    线程池的简单实现

    下面将详细讨论线程池的原理及其在Java中的实现。 首先,我们来看`ThreadPoolManager`类,这个类通常用于管理线程池,包括初始化线程池、提交任务以及关闭线程池等操作。线程池的大小可以通过参数设置,可以根据...

    线程池的实现以及底层原理.docx

    "线程池的实现以及底层原理" 线程池是Java多线程编程中的一种常见技术,能够提高系统的性能和可靠性。本文将详细介绍线程池的实现原理、线程池的优势、线程池的类型、线程池的创建方式以及线程池的使用注意事项。 ...

    Linux C线程池简单实现实例

    ### Linux C线程池简单实现实例 #### 概述 在多线程编程中,线程池是一种广泛采用的设计模式。它通过预先创建多个线程,并将它们组织成一个池,来处理提交的任务,从而避免了频繁创建与销毁线程所带来的性能开销。...

    简单线程池与线程池检查的实现

    标题 "简单线程池与线程池检查的实现" 涉及到的是计算机编程中的多线程管理和优化,特别是线程池的概念及其检查机制。线程池是一种多线程处理形式,预先创建一定数量的线程,放入池中,当有任务需要执行时,直接从池...

    VC++ 线程池(ThreadPool)实现

    本文将深入探讨VC++中线程池的实现,并提供一个简单的实现示例。 线程池的基本概念: 线程池是由一组工作线程组成的集合,这些线程预先创建并处于待命状态,等待执行由应用程序提交的任务。当一个任务被提交到...

    c++简单线程池的实现

    本文将深入探讨如何在Visual Studio 2015(VS2015)环境下实现一个简单的线程池,并解析提供的`TestThreadPool.sln`解决方案和`TestThreadPool`源代码文件。 线程池的基本思想是维护一组预先创建的线程,这些线程...

    C++实现线程池详解(基于boost源码以及封装等线程池)

    三、简单的C++线程池代码示例 四、 基于boost编写的源码库 - 线程池 4.1 基于boost编写的源码库地址 4.2 boost线程池的先进先出、后进先出、优先级代码示例 五、看看人家线程池怎么写的 - 要理解精髓 六、线程池应用...

    线程池的实现java

    线程池的实现,简单的实现了线程池的功能,稍微改动就可以应用到项目中了

    易语言-易语言真正的线程池简易实现

    易语言简易线程池的实现 ——V雪落有声V原创 转载请保留 前文: 为了能充分理解本篇文章的内容,需要了解的知识如下: 1.事件对象的使用:http://baike.baidu.com/view/751499.htm 2.信号量的使用:...

    简单的线程池的.net实现

    本项目"简单的线程池的.net实现"提供了一个自定义线程池的示例,帮助开发者更好地理解和运用线程池。 首先,线程池的主要优点在于其资源管理效率。当任务到达时,线程池会检查是否有空闲线程可供使用,如果有的话,...

    使用Vector实现简单线程池

    然而,如果我们想要从头开始理解线程池的工作原理,或者在特定场景下自定义线程池的行为,那么使用`Vector`来实现简单的线程池是一个很好的学习实践。 标题"使用Vector实现简单线程池"指的是将Java中的`Vector`类...

    线程池实现,通过C语言实现

    在给定的资源中,"200行C代码实现简单线程池.doc"可能包含了详细的设计和实现步骤,以及如何在实际项目中应用线程池的文档。而"threadpool.c"则是实际的C语言源代码文件,实现了线程池的核心功能。下面我们将探讨...

Global site tag (gtag.js) - Google Analytics