线程池的简单调用(附动态图)

【前言】
    在实际工作中,很少会执行new Thread做多线程处理,而是会创建好线程池,再调用线程池资源。
    就像连接数据库,从来不会说,用JDBC建立连接,而是用数据库连接池,Netty通信也是建个Channel通道池。
    单独建个JDBC要加载驱动,写URL 数据库配置信息,还得关闭连接,每次都得来一遍很麻烦。new Thread也是一样,每次new Thread都要新建个对象,而且线程也缺乏统一的管理,总不可能每次都给线程命名,如果不小心在循环中new了,还可能出现,不停建新线程直至死机,一些高级的功能,更多执行、定期执行、线程中断也没有。
    而线程池就不一样了,前提建好线程,可以重复使用,设置好最大并发数,也不会出现无限制新建线程的情况,定时执行、定期执行、并发数控制这些高级功能也都有。
【正文】

    线程池--ThreadPoolExecutor
    public void ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               long keepAliveTime,
               TimeUnit unit,
               BlockingQueue workQueue,
               ThreadFactory threadFactory,
               RejectedExecutionHandler handler) {}

    参数:
    corePoolSize    核心线程数量
    maximumPoolSize    最大线程数量
    keepAliveTime      空闲线程存活时间
    unit    存活时间的单位
    workQueue    阻塞队列,存储等待执行的任务,很重要,对线程池运行影响很大
    threadFactory    线程工厂,创建管理线程
    handler    拒绝处理任务时的策略

    如果存活线程数<核心线程数,直接创建新线程,一般发生在线程池初始化时(维持一定数量备调用);
    如果存活线程数,处于核心和最大之间,阻塞队列没满,先放队列里,只有阻塞队列满,才创建新线程;
    如果存活线程数,超过最大线程数,且阻塞队列满,执行拒绝策略
    好理解的:南京市民大厅,至少开5个窗口(核心线程),市民(任务)超过5个,大厅长椅(阻塞队列)坐得下,就不开新窗口(线程),大厅里坐不下,还有空余窗口(最大线程),就多开窗口,要是窗口全开了,大厅还坐不下,就通知暂停发号(拒绝策略)。

    方法:
    execute() :提交任务交给线程池处理
    submite() :提交任务,能够返回结果execute+Future
    shutdown() :关闭任务,等待任务都执行完。
    shutdownNow() :关闭任务,不等待任务执行完。
    常用的只有第1种。

    getTaskCount() :已执行和未执行的任务数
    getCompletedTaskCount() :已完成任务数
    getPoolSize() :当前线程数
    getActiveCount() :活跃线程数

    Executor框架接口:
    Executors.newCachedThreadPool 可缓存的线程池,灵活回收创建线程
    Executors.newFixedThreadPool    定长的线程池,控制并发数,超出的线程会在队列等待
    Executors.newScheduleThreadPool     定长的线程池,定时周期执行
    Executors.newSingleThreadPool     单线程池

【线程池配置和使用场景】
    并不是说,随便一个场景都可以使用线程池,如果数据很少(10w)并发很少(100QPS)。这时候花费在线程调度和管理的时间,要比单线程计算的时间还要长,这时候就不要起线程池了。
    一般CPU密集型(计算)的处理任务,线程数可以预设CPU数+1,IO密集型(存储读取)任务,预设2*CPU数,具体调整可以看消耗内存情况。
public class ThreadPool
{
    public static void main(String[] args) {
                //CachedThreadPool结果是乱序的
        ExecutorService executorService=Executors.newCachedThreadPool();
                //FixedThreadPool需要制定coreThread数
                //ExecutorService executorService=Executors.newFixedThreadPool(3);
                //SingleThreadExecutor有序
                //ExecutorService executorService=Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            executorService.execute(new Runnable() {
                public void run() {
                    System.out.println("task:"+index);
                }
            });
        }
        executorService.shutdown();
    }
}

CachedThreadPool结果是乱序的

public class ScheduledThreadPool
{
    public static void main(String[] args) {
                //延迟1秒后,每隔3秒输出当前时间,实现线程调度
        ScheduledExecutorService executorService=Executors.newScheduledThreadPool(3);
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        executorService.scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println(df.format(new Date()));
            }
        }, 1, 3, TimeUnit.SECONDS);
    }
}

延迟1秒后,每隔3秒输出当前时间,实现线程调度

原文地址:https://www.cnblogs.com/likailun/p/8999493.html

时间: 2024-10-27 19:08:48

线程池的简单调用(附动态图)的相关文章

使用Java并发包线程池和XML实现定时任务动态配置和管理

文章标题:使用并发包线程池和XML实现定时任务动态配置和管理 文章地址: http://blog.csdn.net/5iasp/article/details/32705601 作者: javaboy2012Email:[email protected]qq:    1046011462 项目结构: 一.采用的知识点: 1. java并发包2. xml配置文件读取3. 反射动态调用类的方法 二. 基本思路 1.  创建线程池: ScheduledExecutorService scheduExe

线程池的简单实现

几个基本的线程函数: //线程操纵函数//创建:   int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void *), void *arg);//终止自身    void pthread_exit(void *retval);//终止其他:   int pthread_cancel(pthread_t tid); 发送终止信号后目标线程不一定终止,要调用join函数等待//阻塞

一个线程池的简单的实现

线程池实现: 用于执行大量相对短暂的任务 当任务增加的时候能够动态的增加线程池中线程的数量直到达到一个阈值. 当任务执行完毕的时候,能够动态的销毁线程池中的线程 该线程池的实现本质上也是生产者与消费模型的应用.生产者线程向任务队列中添加任务,一旦队列有任务到来,如果有等待线程就唤醒来执行任务,如果没有等待线程并且线程数没有达到阈值,就创建新线程来执行任务. contion.h #ifndef _CONDITION_H_ #define _CONDITION_H_ #include <pthrea

线程池? 如何设计一个动态大小的线程池,有哪些方法?

[线程池?  如何设计一个动态大小的线程池,有哪些方法?] 线程池:顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中, 需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中, 从而减少创建和销毁线程对象的开销. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统的交互.此时,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 与数据库连接池相似,线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable

Linux组件封装(七)——线程池的简单封装

线程池的封装,基础思想与生产者消费者的封装一样,只不过我们是将线程池封装为自动获取任务.执行任务,让用户调用相应的接口来添加任务. 在线程池的封装中,我们同样需要用到的是MutexLock.Condition.Thread这些基本的封装. 基础封装如下: MutexLock: 1 #ifndef MUTEXLOCK_H 2 #define MUTEXLOCK_H 3 4 #include "NonCopyable.h" 5 #include <pthread.h> 6 #i

linux 下c++线程池的简单实现(在老外代码上添加注释)

作为一个c++菜鸟,研究半天这个代码的实现原理,发现好多语法不太熟悉,因此加了一大堆注释,仅供参考.该段代码主要通过继承workthread类来实现自己的线程代码,通过thread_pool类来管理线程池,线程池不能够实现动态改变线程数目,存在一定局限性.目前可能还有缺陷,毕竟c++来封装这个东西,资源释放什么的必须想清楚,比如vector存储了基类指针实现多态,那么如何释放对象仍需要考虑,后续我可能会更进一步修改完善该代码,下面贡献一下自己的劳动成果. #include <pthread.h>

QT 线程池 + TCP 小试(一)线程池的简单实现

*免分资源链接点击打开链接http://download.csdn.net/detail/goldenhawking/4492378 很久以前做过ACE + MFC/QT 的中轻量级线程池应用,大概就是利用线程池执行客户机上的运算需求,将结果返回.ACE是跨平台重量级的通信中间件,与常见的应用程序框架需要精心契合,才能不出问题.最近想到既然QT框架本身就已经具有各类功能,何不玩一玩呢,那就开搞!这个实验的代码可以从我的资源内下载. 第一步打算实现的模式,我们需要一个设置为CPU核心数的线程池,这

线程池的简单Demo

服务器端: public class Server { private int port=8821; private ServerSocket serverSocket; private ExecutorService executorService;//线程池 private final int POOL_SIZE=10;//单个CPU线程池大小 public MultiThreadServer()throws IOException{ serverSocket=new ServerSocke

JAVA中线程池的简单使用

比如现在有10个线程,但每次只想运行3个线程,当这3个线程中的任何一个运行完后,第4个线程接着补上.这种情况可以使用线程池来解决,线程池用起来也相当的简单,不信,你看: package com.demo; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public