为什么使用线程池呢?
Java中的线程池是运用场景最多的并发框架,但思考下为什么要使用线程池呢?
(1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
(2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
(3)提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
但是如果想要合理的使用线程池必须呀要理解其原理,才能应用的得心应手 ;
线程池的实现原理
思考下:在使用线程池的情况下,当向线程池中提交一个任务后,线程池是如何处理这个任务的呢?看下图:
从图中可以看出,当提交一个新任务到线程池时,线程池的处理流程如下。
1)线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。
2)线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3)线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程 来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
了解了线程池的原理,那么线程池是如何执行的呢?
线程池的真正实现类是 ThreadPoolExecutor(后文做详解),那基于ThreadPoolExecutor 是如何实现线程池的执行过程呢?参考下图:
主线程通过execute()、submit()方法(思考两个方法的区别)来提交一个任务到线程池,然后经历1 2 3 4过程来实现线程的执行(是不是和线程池实现原理一样呢?),详细分析下:
ThreadPoolExecutor执行execute、submit()方法分下面4种情况。
1)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤 需要获取全局锁)。( 这一步不太理解,欢迎大家解答)
2)如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
3)如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。
4)如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用 RejectedExecutionHandler.rejectedExecution()方法。
ThreadPoolExecutor采取上述步骤的总体设计思路,是为了在执行execute()方法时,尽可能 地避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。在ThreadPoolExecutor完成预热之后 (当前运行的线程数大于等于corePoolSize),几乎所有的execute()方法调用都是执行步骤2,而 步骤2不需要获取全局锁。
源码分析:上面的流程分析让我们很直观地了解了线程池的工作原理,让我们再通过源代 码来看看是如何实现的,线程池执行任务的方法如下。
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
// 如果线程数小于基本线程数,则创建线程并执行当前任务
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
// 如线程数大于等于基本线程数或线程创建失败,则将当前任务放到工作队列中。
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
// 如果线程池不处于运行中或任务无法放入队列,并且当前线程数量小于最大允许的线程数量,
// 则创建一个线程执行任务。
else if (!addIfUnderMaximumPoolSize(command))
// 抛出RejectedExecutionException异常
reject(command); // is shutdown or saturated
}
}
需要提一下的:线程池中执行任务的线程是工作线程;工作线程:线程池创建线程时,会将线程封装成工作线程Worker,Worker在执行完任务
后,还会循环获取工作队列里的任务来执行。我们可以从Worker类的run()方法里看到这点。
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
线程池的使用
线程池的创建
了解完了线程池的执行过程,我们来了解下创建ThreadPoolExecutor有哪些方法:其构造方法有如下4种:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
从上述的构造方法中,我们可以得出几个创建线程池的重要参数 corePoolSize, maximumPoolSize, keepAliveTime, timeUnit,workQueue, threadFactory,rejectedExecutionHandler ;为了创建合理的线程池,我们需要详细了解下以上参数的意义;
corePoolSize(必需): 线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize, 即使有其他空闲线程能够执行新来的任务, 也会继续创建线程;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。 注意一点核心线程数 一旦创建后,默认情况下,核心线程会一直存活 不会随着任务的减少(小于核心线程数)而中断,会继续存活,等待新的任务加入到线程池 ,但是当将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
maximumPoolSize(必需) :线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。注意:与核心线程不同的是,非核心线程会随着任务的减少的中断,也就是线程闲置时,超过keepAliveTime 指定值,将会被回收。
keepAliveTime(必需) :线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
unit(必需): 指定 keepAliveTime 参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)TimeUnit.MINUTES(分)。
threadFactory(可选): 用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设更有意义的名字。使用开源框架guava提供的ThreadFactoryBuilder可以快速给线程池里的线 程设置有意义的名字,代码如下。
new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build();
workQueue (必需): 用来保存等待被执行的任务的阻塞队列. 在JDK中提供了如下阻塞队列: 具体可以参考JUC 集合: BlockQueue详解
任务队列。通过线程池的 execute() 方法提交的 Runnable 对象将存储在该参数中。其采用阻塞队列实现。
ArrayBlockingQueue: 基于数组结构的有界阻塞队列,按 先进先出FIFO排序任务;
LinkedBlockingQuene: 基于链表结构的阻塞队列,按先进先出FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene;
SynchronousQuene: 一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene; 静态工厂方法Executors.newCachedThreadPool使用了这个队列
PriorityBlockingQuene: 具有优先级的无界阻塞队列;
LinkedBlockingQueue比ArrayBlockingQueue在插入删除节点性能方面更优,但是二者在put(), take()任务的时均需要加锁,
SynchronousQueue使用无锁算法,根据节点的状态判断执行,而不需要用到锁,其核心是Transfer.transfer().
LinkedBlockingQueue比ArrayBlockingQueue在插入删除节点性能方面更优,但是二者在put(), take()任务的时均需要加锁,
SynchronousQueue使用无锁算法,根据节点的状态判断执行,而不需要用到锁,其核心是Transfer.transfer().
rejectedExecutionHandler(可选):拒绝策略。 当达到最大线程数时需要执行的饱和策略。当队列和线程池都满了,说明线程池处于饱和状
态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。
在JDK 1.5中Java线程池框架提供了以下4种策略。
AbortPolicy:直接抛出异常。 (默认)
CallerRunsPolicy:只用调用者所在线程来运行任务。
DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
DiscardPolicy:不处理,直接丢弃掉。
当然,也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化存储不能处理的任务。
上面介绍的是通过ThreadPoolExecutor 创建线程池的方法,也是推荐创建线程池的方式,这样有助于我们全面了解线程池。
Java中还有一个别的方式可以创建线程池,可以作为了解:从ThreadPoolExecutor的构造方法中有一个工具类:Executors,可以通过该工具类创建以下几种类型的线程池
newFixedThreadPool (固定大小的线程池)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
线程池的线程数量达corePoolSize后,即使线程池没有可执行任务时,也不会释放线程。
FixedThreadPool的工作队列为无界队列 LinkedBlockingQueue(队列容量为Integer.MAX_VALUE), 这会导致以下问题:
线程池里的线程数量不超过corePoolSize,这导致了maximumPoolSize和keepAliveTime将会是个无用参数
由于使用了无界队列, 所以FixedThreadPool永远不会拒绝, 即饱和策略失效
newSingleThreadExecutor (单个线程的线程池)
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
初始化的线程池中只有一个线程,如果该线程异常结束,会重新创建一个新的线程继续执行任务,唯一的线程可以保证所提交任务的顺序执行。
由于使用了无界队列, 所以SingleThreadPool永远不会拒绝, 即饱和策略失效
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
线程池的线程数可达到Integer.MAX_VALUE,即2147483647,内部使用SynchronousQueue作为阻塞队列;和newFixedThreadPool创建的线程池不同,newCachedThreadPool在没有任务执行时,当线程的空闲时间超过keepAliveTime,会自动释放线程资源,当提交新任务时,如果没有空闲线程,则创建新线程执行任务,会导致一定的系统开销;执行过程与前两种稍微不同:
主线程调用SynchronousQueue的offer()方法放入task, 倘若此时线程池中有空闲的线程尝试读取 SynchronousQueue的task, 即调用了SynchronousQueue的poll(), 那么主线程将该task交给空闲线程. 否则执行(2)
当线程池为空或者没有空闲的线程, 则创建新的线程执行任务.
执行完任务的线程倘若在60s内仍空闲, 则会被终止. 因此长时间空闲的CachedThreadPool不会持有任何线程资源.
ScheduledThreadPool 定时线程池 (之后详细说明)
上面说过了线程池的创建,接下来说下:
线程的提交
首先线程提交共有两种方式,上面讲述ThreadPoolExecutor 我们说过,
也就是:execute()、submit()方法;那么这两种方法有什么不同呢?
推荐参考:线程池的submit和execute的区别_guhong5153的博客-CSDN博客_线程池submit和execute区别 https://blog.csdn.net/guhong5153/article/details/71247266
execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。
通过以下代码可知execute()方法: 输入的任务是一个Runnable类的实例。 通过Runnable 接口的run方法可以明白,execute()方法没有返回值的原因;
threadsPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个 future对象可以判断任务是否执行成功;注意下:
使用submit方法的话,任务类是必须实现Callable接口还是Callable和Runnable接口都可以呢?
都可以,但是想要拿到返回值的话只能用callable
并且可以通过future的get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,
而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线 程一段时间后立即返回,这时候有可能任务没有执行完。
Future future = executor.submit(harReturnValuetask);
try {
Object s = future.get();
} catch (ExecutionException e) {
// 处理无法执行任务异常
} finally {
// 关闭线程池
executor.shutdown();
}
了解了线程的提交,那么如何关闭线程池呢?
关闭线程池
关闭线程池:可以通过调用线程池的shutdown()或shutdownNow()方法来关闭线程池。
它们的原理是遍历线 程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程 ,所以无法响应中断的任务 可能永远无法终止。但是它们存在一定的区别:
shutdownNow():首先将线程池的状态设置成 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表,
shutdown():只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。
只要调用了这两个关闭方法中的任意一个,isShutdown()方法就会返回true。
当所有的任务都已关闭后,才表示线程池关闭成功,这时调用 isTerminaed()方法会返回true。
至于应该调用哪 一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown()方法来关闭线程池,
如果任务不一定要执行完,则可以调用shutdownNow()方法。
注意: 线程池的关闭要结合实际的场景来选择 shutdown()或shutdownNow() 方法;或者不做关闭处理也是可以的。
线程池的五种状态以及状态之间的切换
通过上面的讲述我们了解的 线程池的创建 线程的提交 线程池的关闭 。那么这里我们就有必要说下线程池的五种状态。(重点哦)
RUNNING = 1 COUNT_BITS; //高3位为111
SHUTDOWN = 0 COUNT_BITS; //高3位为000
STOP = 1 COUNT_BITS; //高3位为001
TIDYING = 2 COUNT_BITS; //高3位为010
TERMINATED = 3 COUNT_BITS; //高3位为011
1、RUNNING
(1) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
(2) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处 于RUNNING状态,并且线程池中的任务数为0!
2、 SHUTDOWN
(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING---->SHUTDOWN。
3、STOP
(1) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中 断正在处理的任务。
(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) ----> STOP。
4、TIDYING
(1) 状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING 状态。
当线程池变为TIDYING状态时,会执行钩子函数 terminated()。
terminated()在 ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的 任务为空时,就会由STOP -> TIDYING。
5、TERMINATED
(1) 状态说明:线程池彻底终止,就变成TERMINATED状态。
(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING - > TERMINATED。
进入TERMINATED的条件如下:
线程池不是RUNNING状态;
线程池状态不是TIDYING状态或TERMINATED状态;
如果线程池状态是SHUTDOWN并且workerQueue为空;
workerCount为0;
设置TIDYING状态成功。
华丽分割线 到此可以算是:介绍完了线程池的原理和使用方法。下面还有很多呢。继续加油哦!下面留个小尾巴。。。。
线程池的体系架构
线程池的体系架构可以让我们更全面了解线程池,接下来 根据类、接口的维度来聊聊线程池
你可能感兴趣的:(并发编程,并发编程,多线程,线程池)
常见的几种设计模式(详细)——应用场景和实现方式
QiuYanping_
设计模式 单例模式 观察者模式 工厂方法模式 装饰器模式 策略模式 责任链模式
文章目录单例模式应用实现工厂模式应用实现❓策略模式应用实现⚖️代理模式应用实现观察者模式(发布订阅模式)应用实现装饰器模式应用实现模版方法模式应用实现⛓️责任链模式应用实现单例模式整个程序运行过程中,类只有一个实例,减少内存消耗应用资源管理:需要共享的资源如数据库连接池、线程池等,确保只有一个实例管理这些资源全局配置:配置类日志记录器:在多线程或分布式环境中确保日志记录器唯一性实现实现时注意:构
使用 ReentrantLock 替代 synchronized 关键字原
幻想之境的探索
编程
在Java并发编程中,我们经常需要处理多线程之间的同步问题。在早期的Java版本中,我们可以使用synchronized关键字来实现线程的同步。然而,Java5引入了一个更强大和灵活的同步机制——ReentrantLock,它提供了与synchronized关键字类似的功能,并且还具有更多的特性和优势。ReentrantLock是一个可重入的互斥锁,它允许线程在获取锁之后多次进入同步代码块,并且能
最全JAVA面试题及答案(200道)
Java布道者
java 开发语言
最近很多同学在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:多线程、JVM、Spring、MySQL、Redis、Dubbo…等内容,希望对找工作的同学有所帮助。文末有题目答案~Java多线程面试题并发编程三要素?同步方法和同步块哪个是更好的选择?谈谈原子性?哪些使用到了?谈谈可见性?哪些使用到了?谈谈有序性?举一个例子?什么是线程池?线程池有哪些创建方式?
【Python爬虫①】专栏开篇:夯实Python基础
奔跑吧邓邓子
Python爬虫 python 爬虫 开发语言 基础知识
【Python爬虫】专栏简介:本专栏是Python爬虫领域的集大成之作,共100章节。从Python基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取,还涉及数据处理与分析。无论是新手小白还是进阶开发者,都能从中汲取知识,助力掌握爬虫核心技能,开拓技术视野。目录一、引言二、Python语法基础2.1变量2.2数据类型2.3运算
DynamicTp动态线程池组件
@淡 定
python 开发语言
maven引入:org.projectlomboklombokorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-autoconfigure-processorcom.alibaba.bootnacos-config-spring-boot-starter0.2.12org.droma
实现多线程对同一个变量线程共享
贺公子之数据科学与艺术
JavaWeb java 开发语言
在Java中,可以使用synchronized关键字或ReentrantLock类来解决多线程访问同一个变量时可能出现的数据不一致问题。以下是使用synchronized关键字的示例代码:publicclassThreadExample{privatestaticintcount=0;publicstaticvoidmain(String[]args){Runnabletask=()->{for(
NSLock 详解
gp103
ios
NSLock是Objective-C提供的一种轻量级互斥锁,用于保证多线程访问共享资源的安全性。相比@synchronized,它的性能更好,并且提供了更灵活的锁管理方法。1.NSLock的基本使用1)lock和unlock@interfaceSafeCounter:NSObject@property(nonatomic,strong)NSLock*lock;@property(nonatomic
c++ 多线程知识汇总
cv操作贼6
c++ 算法 服务器
一、std::threadstd::thread是C++11引入的标准库中的线程类,用于创建和管理线程1.带参数的构造函数templatestd::thread::thread(F&&f,Args&&...args);F&&f:线程要执行的函数;Args&&...args:可变参数,用于将参数转发到函数f2.方法voidjoin();等待线程结束。注:线程必须是可join的(即线程正在运行且未被分
java中的锁面试题
m0_74823094
面试 学习路线 阿里巴巴 java 开发语言
1、多线程中synchronized锁升级的原理是什么?synchronized是JVM层面的锁,是Java关键字,通过monitor对象来完成,synchronized的实现涉及到锁的升级,具体为无锁、偏向锁、自旋锁、重量级锁synchronized锁升级原理:在锁对象的对象头里面有一个threadid字段,在第一次访问的时候threadid为空,jvm让其持有偏向锁,并将threadid设置为
hivemetastore 连接过多导致sql查询慢
sunxunyong
sql 数据库
MetaStore(DB)修改对应的处理连接数maxConnectionsPerPartition建议设置成100(不能超过最大值300),重启Hive服务。建议值100是根据与工行规模相当集群的设置作参考,尽量大满足连接数请求的同时考虑connection占用资源(如果connection太多会占用太多的内存资源)的角度做出的一个综合评估值。原因分析metastore采用了线程池,若使用连接数达
Golang的并发编程问题解决思路
caihuayuan4
面试题汇总与解析 spring sql java 大数据
Golang的并发编程问题解决思路一、并发编程基础并发与并行在计算机领域,“并发”和“并行”经常被混为一谈,但它们有着不同的含义。并发是指一段时间内执行多个任务,而并行是指同时执行多个任务。在Golang中,通过goroutines实现并发、通过通道实现并行,使得并发编程变得简单而高效。是作为Go语言并发体系的核心而引入的概念,它是一种比线程更加轻量级的并发单元。可以使用关键字go来启动一个新的g
Python编程实例-深入了解Python多线程
视觉与物联智能
Python编程实例 python 开发语言 pycharm 多线程 并发
深入了解Python多线程文章目录深入了解Python多线程1、Python中的线程2、启动一个线程3、守护线程(DaemonThreads)4、处理多个线程5、使用ThreadPoolExector6、竞争条件7、使用Lock实现基本同步8、死锁9、生产者-消费者线程(使用锁)10、生产者-消费者线程(使用队列)11、与Thread相关的其他对象Python线程允许同时运行程序的不同部分并可以简
【python】并发编程——多线程
南隅。
python 开发语言
文章目录1一些概念1.1线程概念1.2线程模型1.2.1多对一1.2.2一对一1.2.3多对多1.2.4双层模型2ThreadinPython2.1threading2.1.1示例2.1.2关于线程返回值设置保存运行结果的全局变量重写Thread类2.2concurrent.future线程池2.2.1例程2.2.2死锁的情况相互等待worker不够用3参考1一些概念1.1线程概念线程是程序的执行
关于Qt中QThreadPool的清理
「已注销」
编程 python qt5 pyqt5
最近学习了下PyQt5编程,遇到一个问题,就是QThreadPool的清理。具体说来就是我有时需要停下一个QThreadPool中所有线程的执行,并做必要的清理。这里的有时主要有两个场景:因为新的输入QThreadPool要清理后从新的输入开始;关闭窗口程序退出。第一个场景中的一个是搜索关键词去网络上抓取图片,抓取是在线程池中执行的,然后返回图片数据通过slot在GUI上显示出来,新的搜索与之前的
java多线程进阶(九)ConcurrentHashMap
烟锁迷城
进阶 源码 多线程 java 开发语言
目录1、简单介绍1.2、常见方法1.2.1、computeIfAbsent:如果不存在则初始化1.2.2、computeIfPresent:如果存在则修改1.2.3、compute:无论是否存在,都将数值赋予1.2.4、merge:合并2、数据结构2.1、put方法2.1.1、初始化2.1.2、创建新节点2.1.3、辅助扩容2.1.4、插入算法2.1.5、treeifyBin:辅助扩容与红黑树转换
Chrome内核解析 -- 背景篇:Chromium的多进程多线程构架
yunchao_he
Chromium/Blink Rendering Chromium multi-process
转载请注明出处:http://blog.csdn.net/yunchao_he/article/details/41695497Chromium采用多进程构架,以DesktopChromium为例,它包括一个BrowserProcess(也称为UIProcess),一个或多个RenderProcess(也称为WebProcess),零个或一个GPUProcess,以及一个或多个NPAPIPlugi
简介 AMD zen 系列 cpu zen zen+ zen2 zen3 zen4 特性
Eloudy
CPU ZEN
zen系列cpu,几代之间,指令集又什么区别?AMD的Zen系列CPU在不同代之间引入了多种指令集扩展和架构改进。以下是各代之间的主要指令集和功能差异:1.Zen(第一代)指令集:支持x86-64指令集,包括SSE、SSE2、SSE3、SSE4.1、SSE4.2、AVX和AVX2。特点:引入了新的微架构设计,显著提升了多线程性能。支持SMT(SimultaneousMultithreading),
Golang的并发编程案例详解
caihuayuan5
面试题汇总与解析 spring boot java 后端 大数据
Golang的并发编程案例详解一、并发编程概述并发编程是指程序中有多个独立的执行线索,并且这些线索在时间上是重叠的。在Golang中,并发是其核心特性之一,通过goroutine和channel来支持并发编程,使得程序可以更高效地利用计算资源,提高程序的性能和响应速度。二、Goroutine的创建和调度创建Goroutine在Golang中,通过在函数或方法调用前加上关键字go,就可以创建一个go
Executors 的详细用法及与 ThreadPoolExecutor 的关系
java
一、Executors工具类概述Executors是Java并发包(java.util.concurrent)中的一个工具类,提供了一系列静态工厂方法,用于快速创建不同类型的线程池。这些方法内部封装了ThreadPoolExecutor或ScheduledThreadPoolExecutor的配置,简化了线程池的创建过程。二、Executors提供的线程池类型及用法工厂方法线程池类型核心参数配置适
Java进阶篇之线程的创建和运行
code2cat
Java Java进阶 java 开发语言 intellij-idea eclipse ide
引言在前面的文章中,我们介绍了多线程(Java进阶篇之多线程)。在开发高效的并发应用时,线程的创建与运行是我们需要掌握的基本技能。线程能够让我们同时处理多个任务,充分利用多核CPU提高程序的执行效率。Java提供了多种方式来创建和启动线程,从简单的继承Thread类到实现Runnable接口,再到使用现代的ExecutorService,每种方式都有其适用的场景。今天,我们就来聊一聊Java中线程
分布式数据库面试整理
Necther
数据库 面试 分布式
5.3.1redis面试专题1、redis和memcached什么区别?为什么高并发下有时单线程的redis比多线程的memcached效率要高?区别:mc可缓存图片和视频。rd支持除k/v更多的数据结构;rd可以使用虚拟内存,rd可持久化和aof灾难恢复,rd通过主从支持数据备份;3.rd可以做消息队列。原因:mc多线程模型引入了缓存一致性和锁,加锁带来了性能损耗。2、redis主从复制如何实现
【爬虫案例】2025最新python爬虫案例!5个经典案例!(完整代码)
小北画画
爬虫 python 开发语言 蓝桥杯 职场和发展 pycharm
文章目录案例1:爬取豆瓣电影Top250案例2:爬取猫眼电影Top100案例3:爬取某吧帖子内容案例4:多线程爬取小说章节内容案例5:爬取全国高校名单—————其他案例分享—————案例1:爬取豆瓣电影Top250目标:获取豆瓣电影Top250的电影名称、评分和评价人数等信息。方法:使用requests库发送HTTP请求,BeautifulSoup库解析网页内容,csv库保存数据到CSV文件。代码
ThreadPool.QueueUserWorkItem方法 和WaitCallback委托
want fly
c#上位机学习 c# 开发语言
ThreadPool.QueueUserWorkItemThreadPool.QueueUserWorkItem方法是用于将工作项提交到线程池队列中的方法。当你需要执行一个方法但不想创建一个新的线程时,可以使用该方法。这个方法会将工作项放到一个线程池队列中,并由线程池中的一个线程来执行该工作项。方法的第一个参数是WaitCallback委托类型,它表示要在线程池上执行的方法。第二个参数是一个对象,
C++进阶篇:从高手到大师
杨胜增
c++ 开发语言
C++进阶篇:从高手到大师如果你已经掌握了C++的基础知识并开始写出一些较为复杂的程序,接下来该是深入挖掘C++高级特性的时候了。从内存管理的细节到多线程编程,从模板的深度到STL的运用,这篇文章将带你深入C++的核心,帮助你成为C++的真正高手。目录C++内存管理的艺术手动内存管理与智能指针内存泄漏与RAIIC++中的模板编程模板的基本使用高级模板技术:SFINAE与变参模板C++的多线程与并发
CAS 的工作原理
冰糖心158
Java 开发 2025 Java面试系列 java
CAS(Compare-and-Swap)本身并不是一个独立的项目或软件,而是一种底层的硬件指令和并发编程概念1.核心概念CAS是一种原子操作:它的“比较”和“交换”这两个动作是作为一个不可分割的整体执行的,要么都成功,要么都失败,不会出现中间状态。CAS是一种无锁操作(乐观锁):它在操作过程中不会阻塞线程,而是通过不断重试来实现同步。CAS操作三个数:内存位置(V):要读取和修改的内存地址。预期
Tomcat Request Cookie 丢失问题
m0_74825447
面试 学习路线 阿里巴巴 tomcat firefox java
优质博文:IT-BLOG-CN一、问题描述生产环境偶尔(涉及到多线程处理)出现"前端传递`Cookie为空"的告警,导致前端请求丢失,出现请求失败问题。告警内容如下前端传递Cookie为空告警内容:服务端获取requestCookie为空,请尽快处理!!!AppId:xxxxxxip:xx.xx.xxx.xx告警事件:2024-03-15背景:为什么要加Cookie告警:项目出海,需要保证多语言,
C++设计模式——Singleton单例模式
程序员与背包客_CoderZ
C/C++设计模式 c++ 设计模式 单例模式 c语言 开发语言
一、单例模式的定义单例模式,英文全称SingletonPattern,是一种创建型设计模式,它保证一个类在程序中仅有一个实例,并对外提供一个访问的该类实例的全局接口。单例模式通常用于需要控制对象资源的开发场景,一个类只创建一个对象的设计,既可以避免创建过多副本所造成的资源浪费现象,又可以避免引发数据一致性等问题。在数据库连接、线程池设计、日志系统设计等开发场景,经常使用单例模式来创建对象,可以有效
Qt多线程http下载器之四:Win10上使用VS2017编译libcurl
草上爬
Qt小工具 libcurl libssh2 windows
编译libcurl时,libssh2和openssl应该都不是必须的,这从libcur的vs工程配置能看出来这里我们编译DLLRelease-DLLOpenSSL-DLLLibSSH2,win32libssl2依赖zlib和openssl,下载相关源码并解压下载地址https://github.com/madler/zlibhttps://github.com/openssl/opensslhtt
基于 Tauri + Tokio + Rodio 的 Rust 简易音乐播放器桌面程序
senlizishi
rust
导读:笔者最近跟着RustCourse过了一遍Rust的知识点后写了一个练手项目加深一下理解。项目主要依赖Tauri、Tokio、Rodio库。项目中涉及到了结构体、多线程与Arc/Mutex、异步编程与channel通道、生命周期与所有权等知识点。项目概述一个用Rust编写的简单的桌面音乐播放器应用程序。前端基于Tauri(Vue+Typescript),后端主要使用Tokio(异步库)、Rod
Java面试之多线程&并发篇(5)
李老头探索
java 面试 开发语言
前言本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!常用的线程池有哪些?简述一下你对线程池的理解?Java程序是如何执行的?锁的优化机制了解吗?说说进程和线程的区别?似乎有点模糊了,那就大概看一下面试题吧。好记性不如烂键盘***12万字的java面试题整理******java核心面试知识整理******Java高频面试讲解(知识涵盖齐全)***常用的线程池有哪些?newSingleThre
分享100个最新免费的高匿HTTP代理IP
mcj8089
代理IP 代理服务器 匿名代理 免费代理IP 最新代理IP
推荐两个代理IP网站:
1. 全网代理IP:http://proxy.goubanjia.com/
2. 敲代码免费IP:http://ip.qiaodm.com/
120.198.243.130:80,中国/广东省
58.251.78.71:8088,中国/广东省
183.207.228.22:83,中国/
mysql高级特性之数据分区
annan211
java 数据结构 mongodb 分区 mysql
mysql高级特性
1 以存储引擎的角度分析,分区表和物理表没有区别。是按照一定的规则将数据分别存储的逻辑设计。器底层是由多个物理字表组成。
2 分区的原理
分区表由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们可以直接访问各个分区。存储引擎管理分区的各个底层
表和管理普通表一样(所有底层表都必须使用相同的存储引擎),分区表的索引只是
JS采用正则表达式简单获取URL地址栏参数
chiangfai
js 地址栏参数获取
GetUrlParam:function GetUrlParam(param){
var reg = new RegExp("(^|&)"+ param +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null
怎样将数据表拷贝到powerdesigner (本地数据库表)
Array_06
powerDesigner
==================================================
1、打开PowerDesigner12,在菜单中按照如下方式进行操作
file->Reverse Engineer->DataBase
点击后,弹出 New Physical Data Model 的对话框
2、在General选项卡中
Model name:模板名字,自
logbackのhelloworld
飞翔的马甲
日志 logback
一、概述
1.日志是啥?
当我是个逗比的时候我是这么理解的:log.debug()代替了system.out.print();
当我项目工作时,以为是一堆得.log文件。
这两天项目发布新版本,比较轻松,决定好好地研究下日志以及logback。
传送门1:日志的作用与方法:
http://www.infoq.com/cn/articles/why-and-how-log
上面的作
新浪微博爬虫模拟登陆
随意而生
新浪微博
转载自:http://hi.baidu.com/erliang20088/item/251db4b040b8ce58ba0e1235
近来由于毕设需要,重新修改了新浪微博爬虫废了不少劲,希望下边的总结能够帮助后来的同学们。
现行版的模拟登陆与以前相比,最大的改动在于cookie获取时候的模拟url的请求
synchronized
香水浓
java thread
Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然
maven 简单实用教程
AdyZhang
maven
1. Maven介绍 1.1. 简介 java编写的用于构建系统的自动化工具。目前版本是2.0.9,注意maven2和maven1有很大区别,阅读第三方文档时需要区分版本。 1.2. Maven资源 见官方网站;The 5 minute test,官方简易入门文档;Getting Started Tutorial,官方入门文档;Build Coo
Android 通过 intent传值获得null
aijuans
android
我在通过intent 获得传递兑现过的时候报错,空指针,我是getMap方法进行传值,代码如下 1 2 3 4 5 6 7 8 9
public
void
getMap(View view){
Intent i =
apache 做代理 报如下错误:The proxy server received an invalid response from an upstream
baalwolf
response
网站配置是apache+tomcat,tomcat没有报错,apache报错是:
The proxy server received an invalid response from an upstream server. The proxy server could not handle the request GET /. Reason: Error reading fr
Tomcat6 内存和线程配置
BigBird2012
tomcat6
1、修改启动时内存参数、并指定JVM时区 (在windows server 2008 下时间少了8个小时)
在Tomcat上运行j2ee项目代码时,经常会出现内存溢出的情况,解决办法是在系统参数中增加系统参数:
window下, 在catalina.bat最前面
set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms5
Karam与TDD
bijian1013
Karam TDD
一.TDD
测试驱动开发(Test-Driven Development,TDD)是一种敏捷(AGILE)开发方法论,它把开发流程倒转了过来,在进行代码实现之前,首先保证编写测试用例,从而用测试来驱动开发(而不是把测试作为一项验证工具来使用)。
TDD的原则很简单:
a.只有当某个
[Zookeeper学习笔记之七]Zookeeper源代码分析之Zookeeper.States
bit1129
zookeeper
public enum States {
CONNECTING, //Zookeeper服务器不可用,客户端处于尝试链接状态
ASSOCIATING, //???
CONNECTED, //链接建立,可以与Zookeeper服务器正常通信
CONNECTEDREADONLY, //处于只读状态的链接状态,只读模式可以在
【Scala十四】Scala核心八:闭包
bit1129
scala
Free variable A free variable of an expression is a variable that’s used inside the expression but not defined inside the expression. For instance, in the function literal expression (x: Int) => (x
android发送json并解析返回json
ronin47
android
package com.http.test;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import
一份IT实习生的总结
brotherlamp
PHP php资料 php教程 php培训 php视频
今天突然发现在不知不觉中自己已经实习了 3 个月了,现在可能不算是真正意义上的实习吧,因为现在自己才大三,在这边撸代码的同时还要考虑到学校的功课跟期末考试。让我震惊的是,我完全想不到在这 3 个月里我到底学到了什么,这是一件多么悲催的事情啊。同时我对我应该 get 到什么新技能也很迷茫。所以今晚还是总结下把,让自己在接下来的实习生活有更加明确的方向。最后感谢工作室给我们几个人这个机会让我们提前出来
据说是2012年10月人人网校招的一道笔试题-给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码
bylijinnan
java
public class ScalesBalance {
/**
* 题目:
* 给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 (假设N无限大,但一种重量的砝码只有一个)
* 将重物放到天平左侧,问在两边如何添加砝码使两边平衡
*
* 分析:
* 三进制
* 我们约定括号表示里面的数是三进制,例如 47=(1202
dom4j最常用最简单的方法
chiangfai
dom4j
要使用dom4j读写XML文档,需要先下载dom4j包,dom4j官方网站在 http://www.dom4j.org/目前最新dom4j包下载地址:http://nchc.dl.sourceforge.net/sourceforge/dom4j/dom4j-1.6.1.zip
解开后有两个包,仅操作XML文档的话把dom4j-1.6.1.jar加入工程就可以了,如果需要使用XPath的话还需要
简单HBase笔记
chenchao051
hbase
一、Client-side write buffer 客户端缓存请求 描述:可以缓存客户端的请求,以此来减少RPC的次数,但是缓存只是被存在一个ArrayList中,所以多线程访问时不安全的。 可以使用getWriteBuffer()方法来取得客户端缓存中的数据。 默认关闭。 二、Scan的Caching 描述: next( )方法请求一行就要使用一次RPC,即使
mysqldump导出时出现when doing LOCK TABLES
daizj
mysql mysqdump 导数据
执行 mysqldump -uxxx -pxxx -hxxx -Pxxxx database tablename > tablename.sql
导出表时,会报
mysqldump: Got error: 1044: Access denied for user 'xxx'@'xxx' to database 'xxx' when doing LOCK TABLES
解决
CSS渲染原理
dcj3sjt126com
Web
从事Web前端开发的人都与CSS打交道很多,有的人也许不知道css是怎么去工作的,写出来的css浏览器是怎么样去解析的呢?当这个成为我们提高css水平的一个瓶颈时,是否应该多了解一下呢?
一、浏览器的发展与CSS
《阿甘正传》台词
dcj3sjt126com
Part Ⅰ:
《阿甘正传》Forrest Gump经典中英文对白
Forrest: Hello! My names Forrest. Forrest Gump. You wanna Chocolate? I could eat about a million and a half othese. My momma always said life was like a box ochocol
Java处理JSON
dyy_gusi
json
Json在数据传输中很好用,原因是JSON 比 XML 更小、更快,更易解析。
在Java程序中,如何使用处理JSON,现在有很多工具可以处理,比较流行常用的是google的gson和alibaba的fastjson,具体使用如下:
1、读取json然后处理
class ReadJSON
{
public static void main(String[] args)
win7下nginx和php的配置
geeksun
nginx
1. 安装包准备
nginx : 从nginx.org下载nginx-1.8.0.zip
php: 从php.net下载php-5.6.10-Win32-VC11-x64.zip, php是免安装文件。
RunHiddenConsole: 用于隐藏命令行窗口
2. 配置
# java用8080端口做应用服务器,nginx反向代理到这个端口即可
p
基于2.8版本redis配置文件中文解释
hongtoushizi
redis
转载自: http://wangwei007.blog.51cto.com/68019/1548167
在Redis中直接启动redis-server服务时, 采用的是默认的配置文件。采用redis-server xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务。下面是Redis2.8.9的配置文
第五章 常用Lua开发库3-模板渲染
jinnianshilongnian
nginx lua
动态web网页开发是Web开发中一个常见的场景,比如像京东商品详情页,其页面逻辑是非常复杂的,需要使用模板技术来实现。而Lua中也有许多模板引擎,如目前我在使用的lua-resty-template,可以渲染很复杂的页面,借助LuaJIT其性能也是可以接受的。
如果学习过JavaEE中的servlet和JSP的话,应该知道JSP模板最终会被翻译成Servlet来执行;而lua-r
JZSearch大数据搜索引擎
颠覆者
JavaScript
系统简介:
大数据的特点有四个层面:第一,数据体量巨大。从TB级别,跃升到PB级别;第二,数据类型繁多。网络日志、视频、图片、地理位置信息等等。第三,价值密度低。以视频为例,连续不间断监控过程中,可能有用的数据仅仅有一两秒。第四,处理速度快。最后这一点也是和传统的数据挖掘技术有着本质的不同。业界将其归纳为4个“V”——Volume,Variety,Value,Velocity。大数据搜索引
10招让你成为杰出的Java程序员
pda158
java 编程 框架
如果你是一个热衷于技术的
Java 程序员, 那么下面的 10 个要点可以让你在众多 Java 开发人员中脱颖而出。
1. 拥有扎实的基础和深刻理解 OO 原则 对于 Java 程序员,深刻理解 Object Oriented Programming(面向对象编程)这一概念是必须的。没有 OOPS 的坚实基础,就领会不了像 Java 这些面向对象编程语言
tomcat之oracle连接池配置
小网客
oracle
tomcat版本7.0
配置oracle连接池方式:
修改tomcat的server.xml配置文件:
<GlobalNamingResources>
<Resource name="utermdatasource" auth="Container"
type="javax.sql.DataSou
Oracle 分页算法汇总
vipbooks
oracle sql 算法 .net
这是我找到的一些关于Oracle分页的算法,大家那里还有没有其他好的算法没?我们大家一起分享一下!
-- Oracle 分页算法一
select * from (
select page.*,rownum rn from (select * from help) page
-- 20 = (currentPag