2022-06-09 18:24:17.531 [async-task-pool-1] DEBUG c.m.idemo.ThreadPoolTest - 执行中 >>>
2022-06-09 18:24:17.531 [async-task-pool-2] DEBUG c.m.idemo.ThreadPoolTest - 执行中 >>>
2022-06-09 18:24:17.531 [async-task-pool-3] DEBUG c.m.idemo.ThreadPoolTest - 执行中 >>>
2022-06-09 18:24:17.531 [async-task-pool-4] DEBUG c.m.idemo.ThreadPoolTest - 执行中 >>>
在上一篇文章中,我们简单介绍了一下《ThreadPoolExecutor构造方法参数含义》。在实际开发场景中,我们推荐为每一个自定义的线程池都设置不同的线程名前缀,方便后续问题的处理。整体的思路也比较简单:1.创建一个ThreadFactory实现类,NamedThreadFactory;2.创建NamedThreadFactory对象的时候,设置好线程名前缀;3.执行newThread方法时,拼接线程名前缀;......
在JDK的源码使用工厂模式,ThreadFactory就是其中一种。
在我们一般的使用中,创建一个线程,通常有两种方式:
继承Thread类,覆盖run方法,实现我们需要的业务
继承Runnable接口,实现run方法,实现我们需要的业务,并且调用new Thread(Runnable)方法,将其包装为一个线程执行
设想这样一种场景,我们需要一个线程池,并且对于线程池中的线程对象,赋予统一的线程优先级、统一的名称、甚至进行统一的业务处理或和业务方面的初始化工作,这时工厂方法就是最好用的方法了
ThreadFactory接口
ThreadFactory接口很简单,源码如下:
public int
参考DefaultThreadFactory重写一个自定义线程池名称的ThreadFactory
**目的:**当我们手动创建线程池的时候,也可以自定义当前线程池的名称,更好的区分,同时对相同的线程池,也可以进行分组显示。如上图,pool-开头的是默认的线程池名称,如果我们创建多个相同的线程池,也会有分组显示pool-1/2。
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicIntege
本文讲一下Java线程池中创建 ThreadFactory 设置线程名称的三种方式。设置线程名称是很重要的,如果你没有设置过,说明你还“涩世”不深,这里面的坑还不曾踩过,而我 在坑里进去然后坑里出来,被坑的那是一个相当的爽啊~
为了让不重蹈我的覆辙,为了未来不说起来都是满眼含着“热泪”,还是看下如何设置,顺便也设置设置。
第一种 CustomizableThreadFactory
第二种 ThreadFactoryBuilder
在工作中使用线程池,万一线程抛出异常了,日志不好记录到底是哪个线程池抛出的异常;所以为了方便排查,给线程池的线程自定义命名,主要方法就是重写生产线程工厂的命名方法。下面代码示范
集成线程工厂重写
public class NamedThreadFactory implements ThreadFactory {
private static final AtomicInteger...
* 命名的ThreadFactory,方便监控线程
* 修改自 java.util.concurrent.Executors.DefaultThreadFactory
public class NamedThreadFactory implements ThreadFactory {
private static final AtomicInteger
大家有没有想过 线程池中的线程是从哪里来的呢?
之前介绍过,线程池的主要作用是为了线程复用,也就是避免了线程的频繁创建,但是,最开始的那些线程从何而来呢?答案就是ThreadFactory(根据需要创建新线程的对象。使用线程工厂,允许应用程序使用特殊的线程子类、优先级等。)
ThreadFactory 是一个接口,它只有一个用来创建线程的方法。
Thread newThread (Runnable r);
//r:一个由新的线程实例执行的可运行程序
当线程池需要新建线程时,就会调用这个方法。
自定义线程池
ThreadPoolTaskExecutor类,其本质是对java.util.concurrent.ThreadPoolExecutor的包装。这个类则是spring包下的,是Spring为我们开发者提供的线程池类
Spring提供了xml给我们配置ThreadPoolTaskExecutor线程池,但是现在普遍都在用SpringBoot开发项目,所以直接上yaml或者properties配置即可,或者也可以使用@Configuration配置也行,下面演示配置和使用。
application.pro
首先,我们需要重写QWidget的mousePressEvent和mouseMoveEvent两个事件函数。
在mousePressEvent中,我们需要记录下鼠标按下时的坐标和窗口左上角的坐标,以便计算窗口移动的偏移量。
在mouseMoveEvent中,我们需要计算鼠标移动的偏移量,并将窗口的位置进行相应的调整。
以下是示例代码:
```cpp
void MyWindow::mousePressEvent(QMouseEvent *event)
if (event->button() == Qt::LeftButton)
m_dragPosition = event->globalPos() - frameGeometry().topLeft();
void MyWindow::mouseMoveEvent(QMouseEvent *event)
if (event->buttons() & Qt::LeftButton)
QPoint newPos = event->globalPos() - m_dragPosition;
move(newPos);
在上面的代码中,m_dragPosition是一个QPoint类型的成员变量,用于记录鼠标按下时的坐标和窗口左上角的坐标的差值。
最后,我们需要在窗口的构造函数中设置窗口的样式为Qt::FramelessWindowHint,以去掉窗口的边框和标题栏。
完整的示例代码如下:
```cpp
#include "mywindow.h"
#include <QMouseEvent>
MyWindow::MyWindow(QWidget *parent)
: QWidget(parent)
setFixedSize(400, 300);
setWindowFlags(Qt::FramelessWindowHint);
void MyWindow::mousePressEvent(QMouseEvent *event)
if (event->button() == Qt::LeftButton)
m_dragPosition = event->globalPos() - frameGeometry().topLeft();
void MyWindow::mouseMoveEvent(QMouseEvent *event)
if (event->buttons() & Qt::LeftButton)
QPoint newPos = event->globalPos() - m_dragPosition;
move(newPos);
希望这个简单的示例对您有所帮助。