java 线程池详解

Java 线程池(Thread Pools)详解 线程池是一种重用线程的机制,用于提高线程的利用率和管理线程的生命周期,常用于多线程编程和异步编程。Java提供了多种线程池实现,其中最常用的是ThreadPoolExecutor类和Executors类提供的静态工厂方法。线程池由一个线程队列和一个任务队列组成,线程队列中保存着空闲线程,任务队列中保存着等待执行的任务。线程池启动后,线程池中的线程从任务队列中获取任务并执行,执行完毕后返回线程队列中等待下一次任务的到来。如果任务队列为空,线程池中的线程将等待新的任务到来或被关闭。 阅读详情
今天学习下线程池的使用以及原理,还是对着java并发编程艺术这本书讲解的,线程池主要用于需要异步或并发执行任务的程序都可以使用线程池,为什么要使用线程池,而不是自己去创建线程呢?使用线程池三个优点:

1:将低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗,如果你不使用线程池,而是自己去创建线程,比如要100个线程你都要去创建的话,内存也吃不消,这就大大消耗了内存,既然你创建消耗了内存,所以你线程执行完销毁也是需要消耗内存的.

2:提高响应速度:当任务达到时,认为可以不需要等待线程创建就能立即执行

3:提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,这是指消耗cpu,因为cpu要分配时间片给线程执行,还会降低系统的稳定性,线程多了,出错的概率就越大,并发本来就比较难把握.

当我们向线程池提交一个任务之后,线程池是如何处理这个任务呢?线程池处理线程的流程如下:

1:线程池判断核心线程池里的线程是否都在执行.如果不是,则创建一个新的工作线程来执行,如果核心线程池里的都在执行任务,则进入第二步:

2:线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里,如果工作队列满了,则进入第三步

3:判断线程池的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务,如果已经满了,则交给饱和策略来处理这个任务.

现在画一个流程图对线程池的流程做个梳理:

在java中线程池用ThreadPoolExecutor类表示,要实例化这个对象呢?有二种方法,一种是直接new,一种是通过jdk给我们提供的工具类Executors,Executors是单例的

现在看下ThreadPoolExecutor类的构造函数:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

参数说明:

1:corePoolSize:线程池中核心线程数,当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行任务也会创建线程,等到需要执行的任务大于线程池中的核心线程数,就不会再创建,如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程

2:maximumPoolSize:线程池最大线程数,也就是线程池允许创建的最多线程数,如果队列满了,并且已创建的线程数小于线程池设置的最多线程数,则线程池会再创建新的线程执行任务,注意,如果使用了无界的任务队列这个参数就不起什么作用.

3:keepAliveTime:(线程活动保持的时间)线程池的工作线程空闲后,保持存活的时间,如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程的利用率

4:unit(线程活动保持时间的单位):可选的单位有天DAYS,小时HOURS,分钟MINUTES,毫秒MILLISECONDS,微妙MICROSECONDS,千分之一毫秒和纳秒NANOSECONDS=千分之一微妙

5:workQueue(阻塞队列),用于保存等待执行任务的阻塞队列,jdk提高了好几种阻塞队列,这个会等下细讲6:threadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置一个更有意义的名字,一般很少使用.

7:handler(饱和策略),当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务,这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常,在jdk1.5中线程池框架提供了4种策略:AbortPolicy:直接抛出异常CallerRunsPolicy:只用调用者所在线程来执行任务DisCardOldestPolicy:遗弃队列里最近的一个任务,并执行当前任务.DiscardPolicy:不处理,直接遗弃,来自网上的一张图:


线程池执行二种方式

当我们创建好了线程池对象后,就可以向线程池提交任务,提交任务有种方式,分别有execute()和submit(),

execute()方法提交任务不需要返回值,所以无法判断任务是否被线程池执行成功

submit():执行线程有返回值,线程池会返回一个Future类型的对象,通过这个future对象判断任务是否执行成功,并且可以通过future对象的get方法来获取返回值,get()方法会阻塞当前线程直到任务完成,

关闭线程池

关闭线程可以调用线程池的shutdown()方法或者shutdownNow()方法,它的原理是遍历线程池中的所有正在执行任务的线程,然后每个线程调用interrupt方法来中断线程,所以无法响应中断的线程可能无法终止,但是这个二个方法有一定的区别:shutdownNow()首先将线程池的状态设置为stop,然后尝试停止所有正在执行或者暂停执行的线程,并返回等待执行任务的列表,而shutdown()只是将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程.只要调用了这二个方法中的其中一个,isShutdown方法会返回true,当所有的任务都已关闭,才表示线程池关闭成功,这时调用isTerminaed方法会返回true,至于要调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性来决定,通常调用shutdown方法来关闭线程池,如果任务不一定要执行完,则可以调用shutdownNow方法

线程池其他方法

 public long getTaskCount()获取执行任务的个数 

protected void beforeExecute(Thread t, Runnable r)在线程池执行前

protected void afterExecute(Runnable r, Throwable t)在线程池执行后

protected void terminated() { }线程池是否执行完毕

public int getActiveCount()获取正在执行任务的个数

public int getPoolSize() 获取线程池的大小

public boolean remove(Runnable task)移除一个任务

public BlockingQueue<Runnable> getQueue()获取阻塞队列

public long getKeepAliveTime(TimeUnit unit)获取保持线程池存活的时间

public int getCorePoolSize()获取核心线程数

之前构造函数中有一个参数是队列,现在讲下java中常用的队列

阻塞队列

阻塞队列(BlockingQueue)是一个支持二个附加操作的队列,插入和移除方法

插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满

移除方法:在队列为空时,获取元素的线程会等待队列非空,阻塞队列常用于的场景是生产者和消费者,生产者是向队列中添加线程,消费者是从队列中获取线程

如果BlockQueue是空的,从BlockingQueue获取线程操作将会被阻断进入等待状态,直到BlockingQueue有线程时会被唤醒.同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间才会被唤醒继续操作

阻塞队列插入有三个方法 add(),offer(),put(),但是这三个方法是有区别的:

add():加一个线程到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则报异常 

offer():将线程加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false. 

put():将线程加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续,处于一直阻塞的状态

阻塞队列移除也有对应的几个方法:remove(),poll(),take()

remove()方法直接删除队头的元素:

pool()方法取出并删除队头的元素,当队列为空,返回null;

take()方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常

注意:如果是无界阻塞队列,队列不可能出现 满的情况,所以使用put或者offer方法永远不会被阻塞,而且使用offer方法时,该方法会永远返回true

jdk5提供了4中阻塞队列:

ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序,这个要懂数据结构才好,可惜我现在不懂数据结构,

LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常要高ArrayBlockingQueue,静态工厂方法Executors.newFixedThreadPool()使用了这个队列,默认此队列最大的长度为Integer.MAX_VALUE

SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于ArrayBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列,它支持公平访问队列,默认情况下线程采用非公平性策略访问队列默认情况下是非公平,如果把设置为公平访问队列的话,就调用带boolean类型的构造函数,传递true就会采用先进先出的顺序访问队列

PriorityBlockingQueue:一个具有优先级的无限阻塞队列.默认情况下元素采取自然顺序升序排列,也可以自定义类实现compareTo()方法来指定元素排序规则,或者初始化PriorityBlockingQueue时,指定构造参数Comparator来对元素进行排序,需要注意的是不能保证同优先级元素的排序

现在把类图画下:


平时开发工作中,一般使用线程池都是使用一个工具类去创建一个线程池,这个类就是Executors,其关系类图如下:


Executor框架介绍

Executor框架主要由3部分组成

1:任务,包括被执行需要实现的接口,Runnable或者是Callable接口.

2:任务的执行,包括任务执行机制的核心类Exector,以及继承Executor的ExecutorService接口,Executor框架有二个关键类实现了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)

3:异步计算的结果,包括接口Future和实现Future接口的FutureTask类.

ThreadPoolExecutor通常是使用Executors工厂类来创建,Executors可以创建三种类型的ThreadPoolExecutor,分别是

1:创建固定个数的线程数,

ExecutorService executorService = Executors.newFixedThreadPool(5);

2:创建单个线程数:

ExecutorService executorService = Executors.newSingleThreadExecutor()

3:创建带缓存的线程池

ExecutorService executorService = Executors.newCachedThreadPool();

当然Executors还可以创建定时调度的线程池

Executors.newScheduledThreadPool(5);

这个返回的是ScheduledExecutorService对象,它继承了ExecutorService接口,ScheduledExecutorService适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景.

Executors.newFixedThreadPool()

fixedThreadPool被称为可重用固定线程数的线程池.源码如下:

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
通过源码我们发现FixedThreadPool线程池使用的队列是LinkedBlockingQueue,从上面的源码中发现核心线程数等于线程池最大线程数,keepAliveTime为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止,这里把keepAliveTime设置为0L,意味着多余的空闲线程会被立即终止.

这篇博客好久没一直没把剩下的写完,今天就把剩下的写完。

调用Executors.newFixedThreadPool(5)获取的线程池后执行execute()的流程如下:


因为是采用了无界队列LinkedBlockingQueue,所以有几个参数是无效的,maximumpoolSize,keepAliveTime,以及线程池的拒绝策略.

Executors.newSingleThreadExecutor()

Executors.newSingleThreadExecutor()是使用单个工作线程的线程池,源码如下:

 public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()))
从源码发现corePoolSize和maximumpoolSize都设置为1了,其他参数与上面的一样,队列也是使用LinkedBlockingQueue,工作流程如下:


它的原理其实有一个线程轮询的去判断corePool是否等于1,不等于1就从队列中去取一个线程来执行,
Executors.newCachedThreadPool()

源码如下:

 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
从上面的源码中发现,corePool等于0,maximumPoolSize被设置为Integer.MAX_VALUE,即maximumPoolSize是无界的,这里把KeepAliveTime设置为60L,意思是当线程池中的空闲线程等待新任务的最长时间为60秒,空闲线程超过60秒后将会被终止.这个带缓存的线程池使用了SynchronousQueue作为线程池的队列,这意味着如果主线程提交任务的速度高于maximumPool(线程池中最大线程数)中线程处理任务的速度时,会不断的创建新线程,在某些极端情况下,会因为创建过多线程而耗尽CPU和内存资源.

工作流程如下:


流程说明:

1:首先执行SynchronousQueue.off(Runnable task),如果当前maximumPool中有空闲线程正在执行SynchronousQueue.poll(),那么主线程执行offer操作与空闲线程执行的pool操作匹配成功(也就是判断是否超过了60秒),主线程把任务交给空闲线程执行,execute()方法执行完成,如果超过60秒就走第二步

2:当初始maximumPool为空时,或者maximumPool中当前没有空闲线程时,将没有线程行SynchronousQueue.poll()

,这种情况下将失败,此时会创建一个新线程执行任务,execute()方法执行完成.

3:在第二步新创建的线程将任务执行完后,会执行SynchronousQueue.poll(),这个poll操作会让空闲线程最多在SynchronousQueue中等待60秒,如果60秒钟内主线程提交了一个新任务,那么这个时候空闲线程将执行主线程提交的新任务,否则这个空闲线程将会终止,由于空闲60秒的空闲线程会被终止,因此长时间保持空闲的SynchronousQueue不会使用任何资源.

缓存线程池任务传递的示意图如下:


线程池拒绝策略

比如有这样一个需求,我一次性下载30个文件,

ThreadPoolManager.java

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolManager {
    private static  ThreadPoolManager instance=new ThreadPoolManager();
    private LinkedBlockingQueue<Future<?>> taskQuene=new LinkedBlockingQueue<>();
    private ThreadPoolExecutor threadPoolExecutor;
    public static ThreadPoolManager getInstance() {
        return instance;
    }
    private ThreadPoolManager()
    {
        threadPoolExecutor=new ThreadPoolExecutor(5,10,5, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(5), handler);
        threadPoolExecutor.execute(runable);
    }
    private Runnable runable =new Runnable() {
        @Override
        public void run() {
            while (true)
            {
                FutureTask futrueTask=null;
                try {
                	System.out.println("等待队列     "+taskQuene.size());
                    futrueTask= (FutureTask) taskQuene.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(futrueTask!=null)
                {
                    threadPoolExecutor.execute(futrueTask);
                }
            }
        }
    };
    private RejectedExecutionHandler handler=new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
            	taskQuene.put(new FutureTask<Object>(r,null));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    public <T> void execte(FutureTask<T> futureTask) throws InterruptedException {
        taskQuene.put(futureTask);
    }
}
任务类:

public class HttpTask implements Runnable {
	private String name;
    public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	@Override
    public void run() {
    	System.out.println(name+"线程执行完毕");
    }
}
测试:

import java.util.concurrent.FutureTask;
public class Test {
	public static void main(String[] args) {
		for(int i=0;i<15;i++){
			HttpTask httpTask=new HttpTask();
			httpTask.setName("第"+i+"个");
			try {
				ThreadPoolManager.getInstance().execte(new FutureTask<Object>(httpTask,null));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


运行结果:

等待队列     0
等待队列     14
等待队列     13
第0个线程执行完毕
等待队列     12
第2个线程执行完毕
等待队列     11
第3个线程执行完毕
第1个线程执行完毕
第4个线程执行完毕
等待队列     10
等待队列     9
第5个线程执行完毕
第6个线程执行完毕
等待队列     8
等待队列     7
第7个线程执行完毕
第8个线程执行完毕
等待队列     6
等待队列     5
等待队列     4
等待队列     3
等待队列     2
等待队列     1
第9个线程执行完毕
第11个线程执行完毕
第14个线程执行完毕
等待队列     0
第10个线程执行完毕
第13个线程执行完毕
第12个线程执行完毕
这里就使用了线程池的拒绝策略

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

创建四种策略如下,这些都是RejectedExecutionHandler 的内部类.

总的流程如下:


java实现通用线程池的代码 本文旨在使用Java语言编写一个通用的线程池。当需要使用线程池处理事务时,只需按照指定规范封装好事务处理对象,然后用已有的线程池对象去自动选择空 闲线程自动调用事务处理对象即可。并实现线程池的动态修改(修改当前线程数,最大线程数等)。 立即下载

相关推荐

DVWA全级别详细通关教程

dvwa全级别详细通关教程,暴力破解,命令注入,CSRF跨站请求伪造,文件包含,文件上传​,SQL注入,XSS

m0_62063669的博客 1万+

java 线程池 类图_java中常见的六种线程池详解

之前我们介绍了线程池的四种拒绝策略,了解了线程池参数的含义,那么今天我们来聊聊Java 中常见的几种线程池,以及在jdk7 加入的 ForkJoin 新型线程池首先我们列出Java 中的六种线程池如下线程池名称描述FixedThreadPool核心线程数与最大线程数相同SingleThreadExecutor一个线程的线程池CachedThreadPool核心线程为0,最大线程数为Integer...

weixin_42364855的博客 790

NetApp 7-mode初始化详解(原AGGR重建)及注意事项

没想到有生之年还能再写个7-mode的文章,上次接触可能已将近十年,本次恰巧碰到这个机会,边学习边整理,整整一天时间,碰到了不少坑,作为记录。

RaySun的技术Blog 2751

90%的人以为会用ThreadPoolExecutor了,看了这10张图再说吧

在阿里巴巴手册中有一条建议: 【强制】线程池不允许使用 Executors 去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 如果经常基于Executors提供的工厂方法创建线程池,很容易忽略线程池内部的实现。特别是拒绝策略,因使用Executors创建线程池时不会传入这个参数,直接采用默认值,所以常常被忽略。 下面我们就来了解一下线程池相关的实现原理、API以及实例。 线程池的作用 在实践应用中创建线程池主要是为了:

程序新视界 1558

OpenHarmony系统参数权限配置避坑指南:从param get/set失败到SELinux标签实战

本文深入解析OpenHarmony系统参数权限配置的常见问题与解决方案,涵盖DAC和SELinux双重权限控制机制。通过实战案例演示如何配置`param get/set`权限,解决'Permission denied'错误,并提供三方应用访问参数的安全方案,帮助开发者高效完成系统调试与优化。

weixin_27013291的博客 448

手把手教你用Cadence Virtuoso仿真一个5GHz CMOS分频器:从原理图到后仿,避开那些教科书上没写的坑

本文详细介绍了在Cadence Virtuoso环境中设计5GHz CMOS分频器的完整流程,从原理图设计到后仿真优化,特别关注实际工程中容易被忽视的关键问题。内容涵盖分频器核心指标解析、锁存器拓扑选择、接口设计匹配以及后仿真优化策略,为射频集成电路设计提供实用避坑指南。

weixin_26934905的博客 262

Java线程池详解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Java线程池详解线程池一、线程池类图二、ThreadPoolExecutor类corePoolSize:核心线程数,表示线程池支持的最小线程数;maximumPoolSize 最大线程数,当线程数大于核心线程数后,并且阻塞队列里存放满了等待执行的任务,才会创建一个“临时”新线程从阻塞队列头部取出任务,线程池还能接受maximumPoolSize - corePoolSize个“临时”新线程;keepAliveTime: 保持存活时间,空闲

weixin_45387120的博客 767

基于 Qt C++ 的金融行情交易终端

由于完整的商业级源码非常庞大,我将为你提供一个 **结构完整、可直接编译运行的基础框架**,并详细说明各模块的实现思路和扩展方向。double波动 = quote.lastPrice * (rand()%200 - 100) / 10000.0;// 订单缓存(orderId -> Order)

寒寒豆豆软件公司的博客 191

Java 线程池详解

线程池是一组已经初始化并等待执行任务的线程集合。通过使用线程池,我们可以避免频繁地创建和销毁线程,从而节省资源和减少系统开销。线程池的核心思想是通过复用线程来提高性能。

qq_41591215的博客 1万+

分享一份小度在家1C系列NV2101刷机保姆级教程,轻松解锁第三方应用!(内含详细教程、刷机工具和救砖等工具)

分享一份小度在家1C系列NV2101刷机保姆级教程,轻松解锁第三方应用!(内含详细教程、刷机工具和救砖等工具)

XiaoqiangClub的博客 7154

基于STM32的智能手环心率血氧体温监测系统(完整设计)

本文设计了一款基于STM32单片机的多功能智能手环系统,集成心率、血氧、体温实时监测功能,并支持运动数据管理与健康预警。系统采用MAX30102传感器实现心率血氧监测,DS18B20检测体温,ADXL345进行步数统计,通过OLED屏幕显示数据。研究通过低功耗硬件选型与模块化软件架构设计,实现了多参数同步采集、阈值预警及蓝牙数据传输功能。测试结果表明,系统在健康监测精度、续航能力及用户交互体验上均达到预期目标,为个人健康管理提供了实用解决方案。

3254968421的博客 701

java线程池使用最全详解

线程池使用 前言 在执行一个异步任务或并发任务时,往往是通过直接new Thread()方法来创建新的线程,这样做弊端较多,更好的解决方案是合理地利用线程池,线程池的优势很明显,如下: 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗; 提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行; 方便线程并发数的管控,线程若是无限制的创建,不仅会额外消耗大量系统资源,更是占用过多资源而阻塞系统或oom等状况,从而降低系统的稳定性。线程池能有效管控线程,统一分配、调优,提供资源

qq_40093255的博客 9万+

使用STM32制作智能窗帘控制

以上就是一个简单的基于STM32的智能窗帘控制代码案例。通过感知光线强度和控制步进电机的旋转,我们可以实现智能窗帘的自动开启和关闭。通过定时器的中断来控制步进电机的旋转,从而实现窗帘的开启和关闭动作。最后,我们需要实现主函数和中断函数。在主函数中,我们需要初始化硬件资源,然后进入一个无限循环来不断检测光敏电阻的值,并根据其值来控制窗帘的开启和关闭。接下来,我们需要编写功能函数,用于控制窗帘的开启和关闭。然后,我们需要配置STM32开发环境,并创建一个新的工程。接下来,我们初始化相关的硬件资源。

2401_85258012的博客 276

Java线程池参数详解

线程池是现代并发编程中不可或缺的工具,合理配置线程池参数能够显著提升应用的性能和稳定性。本文将深入剖析线程池的核心参数,包括核心线程数、最大线程数、线程存活时间、任务队列类型及拒绝策略等,结合实际案例帮助读者理解每个参数的作用及调优思路。

2301_80795057的博客 2万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java线程池使用详解ThreadPoolExecutor使用示例

一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 1) 任务(Runnable /Callable) 2) 任务的执行(Executor) 3) 异步计算的结果(Future) 2.3 Executor 框架的使用示意图 三 (重要)ThreadPoolExecutor 类简单介绍 3.1 ThreadPoolExecutor 类分析 3.2 推荐使用 ThreadPoolExecutor 构造函数创建线程池 四 ..

xu_yong_lin的博客 5万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Java 线程池原理详解

本文全面解析Java线程池的实现原理和使用方法。线程池通过复用线程、控制并发数量、任务队列管理等机制提升系统性能。核心类是ThreadPoolExecutor,包含核心线程数、最大线程数、任务队列等关键参数配置。

微笑听雨 2087

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

详解java线程池

前言 java 常用有线程池

u010519674的专栏 385

java线程池详解

一,线程池的优点 1,降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 2,提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。 3,提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。但是要做到合理的利用线程池,必须对其原理了如指掌。 ...

MrLee的博客 1271

java线程池详解及五种线程池方法详解

基础知识 Executors创建线程池 Java中创建线程池很简单,只需要调用Executors中相应的便捷方法即可,比如Executors.newFixedThreadPool(int nThreads),但是便捷不仅隐藏了复杂性,也为我们埋下了潜在的隐患(OOM,线程耗尽)。 Executors创建线程池便捷方法列表: 方法名 功能 newFixedThreadPool(int nThreads) 创建固定大小的线程池 newSingleThreadExecutor()

lixiangchibang的博客 3万+

杂谈——Java线程池详解

在一个应用程序中,我们无可避免地需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。 举个例子,假设我们要去爬三百主流媒体网站,每天要抓一次数据,平均每次开销50毫秒,处理开销2毫秒,则可以开二十五个线程,假设每个网站有十个请求,那么三百个网站就有3000个请求。 从上面我们可以知道,CPU等待时间/CPU执行时间=25:1,这样的开销太大了,而这二...

Searchin_R的博客 4892

Java 线程池使用详解

Java 线程池使用详解

weixin_39527642的博客 433
上一篇: android 手把手教你写数据库框架(第二篇)
下一篇: android 框架之基础装饰设计模式
zhoushenxian
博客等级 码龄12年 453粉丝 549原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值