配置ThreadPoolExecutor
ThreadPoolExecutor为一些Executor 提供了基本的实现,这些Executor 是由Executors中的newCachedThreadPool、newFixedThreadPool和newScheduledThreadExecutor 等工厂方法返回的。ThreadPoolExecutor是一个灵活的、稳定的线程池,允许进行各种定制。
如果默认的执行策略不能满足需求,那么可以通过ThreadPoolExecutor的构造函数来实例化一个对象,并根据自己的需求来定制,并且可以参考Executors的源代码来了解默认配置下的执行策略,然后再以这些执行策略为基础进行修改。ThreadPoolExecutor定义了很多构造函数,在程序清单8-2中给出了最常见的形式。
程序清单8-2 ThreadPoolExecutor的通用构造函数 .
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable>workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler){}
线程的创建与销毁
线程池的基本大小(Core Pool Size)、最大大小(Maximum Pool Size)以及存活时间等因素共同负责线程的创建与销毁。基本大小也就是线程池的目标大小,即在没有任务执行时线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程。线程池的最大大小表示可同时活动的线程数量的上限。如果某个线程的空闲时间超过了存活时间,那么将被标记为可回收的,并且当线程池的当前大小超过了基本大小时,这个线程将被终止。
通过调节线程池的基本大小和存活时间,可以帮助线程池回收空闲线程占有的资源,从而使得这些资源可以用于执行其他工作。(显然,这是一种折衷:回收空闲线程会产生额外的延迟,因为当需求增加时,必须创建新的线程来满足需求。)
newFixedThreadPool 工厂方法将线程池的基本大小和最大大小设置为参数中指定的值,而且创建的线程池不会超时。newCachedThreadPool 工厂方法将线程池的最大大小设置为Integer.MAX VALUE,而将基本大小设置为零,并将超时设置为1分钟,这种方法创建出来的线程池可以被无限扩展,并且当需求降低时会自动收缩。其他形式的线程池可以通过显式的ThreadPoolExecutor构造函数来构造。
管理队列任务
在有限的线程池中会限制可并发执行的任务数量。(单线程的Executor是一种值得注意的
⊖在创建ThreadPoolExecutor初期,线程并不会立即启动,而是等到有任务提交时才会启动,除非调用prestartAllCoreThreads。
开发人员以免有时会将线程池的基本大小设置为零,从而最终销毁工作者线程以免阻碍JVM的退出。然而,如果在线程池中没有使用SynchronousQueue 作为其工作队列(例如在newCachedThreadPool中就是如此),那么这种方式将产生一些奇怪的行为。如果线程池中的线程数量等于线程池的基本大小,那么仅当在工作队列已满的情况下ThreadPoolExecutor 才会创建新的线程。因此,如果线程池的基本大小为零并且其工作队列有一定的容量,那么当把任务提交给该线程池时,只有当线程池的工作队列被填满后,才会开始执行任务,而这种行为通常并不是我们所希望的。在Java 6中,可以通过allowCoreThreadTimeOut来使线程池中的所有线程超时。对于一个大小有限的线程池并且在该线程池中包含一个工作队列,如果希望这个线程池在没有任务的情况下能销毁所有线程,那么可以启用这个特性并将基本大小设置为零。
特例:它们能确保不会有任务并发执行,因为它们通过线程封闭来实现线程安全性。)
在6.1.2节中曾介绍,如果无限制地创建线程,那么将导致不稳定性,并通过采用固定大小的线程池(而不是每收到一个请求就创建一个新线程)来解决这个问题。然而,这个方案并不完整。在高负载情况下,应用程序仍可能耗尽资源,只是出现问题的概率较小。如果新请求的到达速率超过了线程池的处理速率,那么新到来的请求将累积起来。在线程池中,这些请求会在一个由Executor 管理的Runnable 队列中等待,而不会像线程那样去竞争CPU资源。通过一个Runnable 和一个链表节点来表现一个等待中的任务,当然比使用线程来表示的开销低很多,但如果客户提交给服务器请求的速率超过了服务器的处理速率,那么仍可能会耗尽资源。
即使请求的平均到达速率很稳定,也仍然会出现请求突增的情况。尽管队列有助于缓解任务的突增问题,但如果任务持续高速地到来,那么最终还是会抑制请求的到达率以避免耗尽内存。甚至在耗尽内存之前,响应性能也将随着任务队列的增长而变得越来越糟。
ThreadPoolExecutor允许提供一个BlockingQueue 来保存等待执行的任务。基本的任务排队方法有3种:无界队列、有界队列和同步移交(Synchronous Handoff)。队列的选择与其他的配置参数有关,例如线程池的大小等。
newFixedThreadPool和newSingleThreadExecutor 在默认情况下将使用一个无界的LinkedBlockingQueue。如果所有工作者线程都处于忙碌状态,那么任务将在队列中等候。如果任务持续快速地到达,并且超过了线程池处理它们的速度,那么队列将无限制地增加。
一种更稳妥的资源管理策略是使用有界队列,例如ArrayBlockingQueue、有界的LinkedBlockingQueue、PriorityBlockingQueue。有界队列有助于避免资源耗尽的情况发生,但它又带来了新的问题:当队列填满后,新的任务该怎么办?(有许多饱和策略[Saturation Policy]可以解决这个问题。请参见8.3.3节。)在使用有界的工作队列时,队列的大小与线程池的大小必须一起调节。如果线程池较小而队列较大,那么有助于减少内存使用量,降低CPU的使用率,同时还可以减少上下文切换,但付出的代价是可能会限制吞吐量。
对于非常大的或者无界的线程池,可以通过使用SynchronousQueue 来避免任务排队,以及直接将任务从生产者移交给工作者线程。SynchronousQueue不是一个真正的队列,而是一种在线程之间进行移交的机制。要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待接受这个元素。如果没有线程正在等待,并且线程池的当前大小小于最大值,那么ThreadPoolExecutor 将创建一个新的线程,否则根据饱和策略,这个任务将被拒绝。使用直接移交将更高效,因为任务会直接移交给执行它的线程,而不是被首先放在队列中,然后由工作者线程从队列中提取该任务。只有当线程池是无界的或者可以拒绝任务时,SynchronousQueue 才有实际价值。在newCachedThreadPool工厂方法中就使用了SynchronousQueue。
当使用像LinkedBlockingQueue 或ArrayBlockingQueue 这样的FIFO(先进先出)队列时,任务的执行顺序与它们的到达顺序相同。如果想进一步控制任务执行顺序,还可以使用PriorityBlockingQueue,这个队列将根据优先级来安排任务。任务的优先级是通过自然顺序或
这类似于通信网络中的流量控制:可以缓存一定数量的数据,但最终需要通过某种方式来告诉发送端停止发送数据,或者丢弃过多的数据并希望发送端在空闲时重传被丢弃的数据。
Comparator (如果任务实现了Comparable)来定义的。
对于Executor,newCachedThreadPool工厂方法是一种很好的默认选择,它能提供比固定大小的线程池更好的排队性能。当需要限制当前任务的数量以满足资源管理需求时,那么可以选择固定大小的线程池,就像在接受网络客户请求的服务器应用程序中,如果不进行限制,那么很容易发生过载问题。
只有当任务相互独立时,为线程池或工作队列设置界限才是合理的。如果任务之间存在依赖性,那么有界的线程池或队列就可能导致线程“饥饿”死锁问题。此时应该使用无界的线程池,例如1 newCachedThreadPool。
饱和策略
当有界队列被填满后,饱和策略开始发挥作用。ThreadPoolExecutor 的饱和策略可以通过调用setRejectedExecutionHandler来修改。(如果某个任务被提交到一个已被关闭的Executor 时,也会用到饱和策略。)JDK提供了几种不同的RejectedExecutionHandler 实现,每种实现都包含有不同的饱和策略:AbortPolicy、CallerRunsPolicy、DiscardPolicy 和DiscardOldestPolicy。
“中止(Abort)”策略是默认的饱和策略,该策略将抛出未检查的RejectedExecution-Exception。调用者可以捕获这个异常,然后根据需求编写自己的处理代码。当新提交的任务无法保存到队列中等待执行时,“抛弃(Discard)”策略会悄悄抛弃该任务。“抛弃最旧的(Discard-Oldest)”策略则会抛弃下一个将被执行的任务,然后尝试重新提交新的任务。(如果工作队列是一个优先队列,那么“抛弃最旧的”策略将导致抛弃优先级最高的任务,因此最好不要将“抛弃最旧的”饱和策略和优先级队列放在一起使用。)
“调用者运行(Caller-Runs)”策略实现了一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。它不会在线程池的某个线程中执行新提交的任务,而是在一个调用了execute 的线程中执行该任务。我们可以将WebServer示例修改为使用有界队列和“调用者运行”饱和策略,当线程池中的所有线程都被占用,并且工作队列被填满后,下一个任务会在调用execute 时在主线程中执行。由于执行任务需要一定的时间,因此主线程至少在一段时间内不能提交任何任务,从而使得工作者线程有时间来处理完正在执行的任务。在这期间,主线程不会调用accept,因此到达的请求将被保存在TCP层的队列中而不是在应用程序的队列中。如果持续过载,那么TCP层将最终发现它的请求队列被填满,因此同样会开始抛弃请求。当服务器过载时,这种过载情况会逐渐向外蔓延开来——从线程池到工作队列到应用程序再到TCP层,最终达到客户端,导致服务器在高负载下实现一种平缓的性能降低。
这种性能差异是由于使用了SynchronousQueue而不是LinkedBlockingQueue。在Java 6 中提供了一个新的非阻塞算法来替代SynchronousQueue,与Java 5.0 中的SynchronousQueue 相比,该算法把Executor 基准的吞吐量提高了3 倍(Scherer et al.,2006)。
②对于提交其他任务并等待其结果的任务来说,还有另一种配置方法,就是使用有界的线程池,并使用SynchronousQueue 作为工作队列,以及“调用者运行(Caller-Runs)”饱和策略。
当创建Executor时,可以选择饱和策略或者对执行策略进行修改。程序清单8-3 给出了如何创建一个固定大小的线程池,同时使用“调用者运行”饱和策略。
程序清单8-3 创建一个固定大小的线程池,并采用有界队列以及“调用者运行”饱和策略
ThreadPoolExecutor executor
= new ThreadPoolExecutor(N_THREADS,N_THREADS,
0L,TimeUnit. MILLISECONDS,
new LinkedBlockingQueue<Runnable>(CAPACITY));
executor. setRejectedExecutionHandler(
new ThreadPoolExecutor. CallerRunsPolicy());
当工作队列被填满后,没有预定义的饱和策略来阻塞execute。然而,通过使用Semaphore (信号量)来限制任务的到达率,就可以实现这个功能。在程序清单8-4的BoundedExecutor中给出了这种方法。该方法使用了一个无界队列(因为不能限制队列的大小和任务的到达率),并设置信号量的上界设置为线程池的大小加上可排队任务的数量,这是因为信号量需要控制正在执行的和等待执行的任务数量。
程序清单8-4 使用 Semaphore 来控制任务的提交速率
@ThreadSafe
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound){
this. exec =exec;
this. semaphore =new Semaphore(bound);
}
public void submitTask(final 'Runnable command)
throws InterruptedException {
semaphore. acquire();
try {
exec. execute(new Runnable(){
public void run(){
try {
command. run();
}finally {
semaphore. release();
}
}catch (RejectedExecutionException e){
semaphore. release();
}
}
}
线程工厂
每当线程池需要创建一个线程时,都是通过线程工厂方法(请参见程序清单8-5)来完成的。默认的线程工厂方法将创建一个新的、非守护的线程,并且不包含特殊的配置信息。通过指定一个线程工厂方法,可以定制线程池的配置信息。在ThreadFactory 中只定义了一个方法newThread,每当线程池需要创建一个新线程时都会调用这个方法。
然而,在许多情况下都需要使用定制的线程工厂方法。例如,你希望为线程池中的线程指定一个UncaughtExceptionHandler,或者实例化一个定制的Thread 类用于执行调试信息的记录。你还可能希望修改线程的优先级(这通常并不是一个好主意。请参见10.3.1节)或者守护状态(同样,这也不是一个好主意。请参见7.4.2节)。或许你只是希望给线程取一个更有意义的名称,用来解释线程的转储信息和错误日志。
程序清单8-5 ThreadFactory接口
public interface ThreadFactory {
Thread newThread(Runnable r);
}
在程序清单8-6的MyThreadFactory 中给出了一个自定义的线程工厂。它创建了一个新的MyAppThread 实例,并将一个特定于线程池的名字传递给MyAppThread 的构造函数,从而可以在线程转储和错误日志信息中区分来自不同线程池的线程。在应用程序的其他地方也可以使用MyAppThread,以便所有线程都能使用它的调试功能。
程序清单8-6 自定义的线程工厂
public class MyThreadFactory implements ThreadFactory {
private final String poolName;
public MyThreadFactory(String poolName){
this. poolName =poolName;
}
public Thread newThread(Runnable runnable){
return new MyAppThread(runnable,poolName);
}
}
在MyAppThread 中还可以定制其他行为,如程序清单8-7 所示,包括:为线程指定名字,设置自定义UncaughtExceptionHandler向Logger 中写入信息,维护一些统计信息(包括有多少个线程被创建和销毁),以及在线程被创建或者终止时把调试消息写入日志。
程序清单8-7定制 Thread 基类
public class MyAppThread extends Thread {
public static final String DEFAULT_NAME="MyAppThread";
private static volatile boolean debugLifecycle =false;
private static final AtomicInteger created =new AtomicInteger();
private static final AtomicInteger alive =new AtomicInteger();
private static final Logger log =Logger. getAnonymousLogger();
public MyAppThread( Runnable r){ this(r,DEFAULT_NAME);}
public MyAppThread(Runnable runnable, String name){
super(runnable, name+"-"+created. incrementAndGet());
setUncaughtExceptionHandler(
new Thread. UncaughtExceptionHandler(){
public void uncaughtException(Thread t,
Throwable e){
log. log(Level. SEVERE,
"UNCAUGHT in thread"+t. getName(),e);
〕 |
} ) ;
}
public void run(){
//复制debug标志以确保一致的值
boolean debug=debugLifecycle;
if (debug) log. log(Level. FINB,"Created "+getName());
try {
alive. incrementAndGet();
super. run();
}finally {
alive. decrementAndGet();
if (debug) log. log(Level. FINE,"Exiting "+getName());
}
}
public static int getThreadsCreated(){return created. get();}
public static int getThreadsAlive(){return alive. get();}
public static boolean getDebug(){return debugLifecycle;}
public static void setDebug(boolean b){debugLifecycle =b;}
}
如果在应用程序中需要利用安全策略来控制对某些特殊代码库的访问权限,那么可以通过Executor中的privilegedThreadFactory工厂来定制自己的线程工厂。通过这种方式创建出来的线程,将与创建privilegedThreadFactory的线程拥有相同的访问权限、AccessControlContext和contextClassLoader。如果不使用privilegedThreadFactory,线程池创建的线程将从在需要新线程时调用execute 或submit的客户程序中继承访问权限,从而导致令人困惑的安全性异常。
在调用构造函数后再定制ThreadPoolExecutor
在调用完ThreadPoolExecutor的构造函数后,仍然可以通过设置函数(Setter)来修改大多数传递给它的构造函数的参数(例如线程池的基本大小、最大大小、存活时间、线程工厂以及拒绝执行处理器(Rejected Execution Handler))。如果Executor 是通过Executors中的某个(newSingleThreadExecutor除外)工厂方法创建的,那么可以将结果的类型转换为ThreadPoolExecutor以访问设置器,如程序清单8-8所示。
程序清单8-8 对通过标准工厂方法创建的 Executor 进行修改
ExecutorService exec =Executors. newCachedThreadPool();
if (exec instanceof ThreadPoolExecutor)
((ThreadPoolExecutor) exec). setCorePoolSize(10);
else
throw new AssertionError(" Oops, bad assumption");
在Executors中包含一个unconfigurableExecutorService 工厂方法,该方法对一个现有的ExecutorService 进行包装,使其只暴露出ExecutorService的方法,因此不能对它进行配置。newSingleThreadExecutor返回按这种方式封装的ExecutorService,而不是最初的ThreadPoolExecutor。虽然单线程的Executor实际上被实现为一个只包含唯一线程的线程池,但它同样确保了不会并发地执行任务。如果在代码中增加单线程Executor 的线程池大小,那么将破坏它的执行语义。
你可以在自己的Executor 中使用这项技术以防止执行策略被修改。如果将ExecutorService 暴露给不信任的代码,又不希望对其进行修改,就可以通过unconfigurableExecutorService来包装它。.
相关文章:
配置ThreadPoolExecutor
ThreadPoolExecutor为一些Executor 提供了基本的实现,这些Executor 是由Executors中的newCachedThreadPool、newFixedThreadPool和newScheduledThreadExecutor 等工厂方法返回的。ThreadPoolExecutor是一个灵活的、稳定的线程池,允许进行各种定制。 如果默认的执行策略不能满足…...
Yolov5s算法从训练到部署
文章目录 PyTorch GPU环境搭建查看显卡CUDA版本Anaconda安装PyTorch环境安装PyCharm中验证 训练算法模型克隆Yolov5代码工程制作数据集划分训练集、验证集修改工程相关文件配置预训练权重文件配置数据文件配置模型文件配置 超参数配置 测试训练出来的算法模型 量化转换算法模型…...
分布式补充技术 01.AOP技术
01.AOP技术是对于面向对象编程(OOP)的补充。是按照OCP原则进行的编写,(ocp是修改模块权限不行,扩充可以) 02.写一个例子: 创建一个新的java项目,在main主启动类中,写如下代码。 package com.co…...
QT 多对一服务插件 CTK开发(五)
CTK在软件的开发过程中可以很好的降低复杂性、使用 CTK Plugin Framework 提供统一的框架来进行开发增加了复用性 将同一功能打包可以提供多个应用程序使用避免重复性工作、可以进行版本控制提供了良好的版本更新迭代需求、并且支持动态热拔插 动态更新、开发更加简单快捷 方便…...
[Windows]_[初级]_[创建目录和文件的名字注意事项]
场景 在开发Windows程序时,会出现目录生成了,但是函数无法在目录里创建文件,怎么回事?说明 在之前说过Windows上有些字符是不能作为文件名的[1],但是检查了下出问题的目录名没有非法字符,所以不是这个原因。 把文件的绝对路径打印出来就发现了问题,目录名后边带了空格,…...
「QT」QT5程序设计目录
✨博客主页:何曾参静谧的博客 📌文章专栏:「QT」QT5程序设计 目录 📑【QT的基础知识篇】📑【QT的GUI编程篇】📑【QT的项目示例篇】📑【QT的网络编程篇】📑【QT的数据库编程篇】📑【QT的跨平台编程篇】📑【QT的高级编程篇】📑【QT的开发工具篇】📑【QT的调…...
ConcurrentHashMap核心源码(JDK1.8)
一、ConcurrentHashMap的前置知识扫盲 ConcurrentHashMap的存储结构? 数组 链表 红黑树 二、ConcurrentHashMap的DCL操作 HashMap线程不安全,在并发情况下,或者多个线程同时操作时,肯定要使用ConcurrentHashMap 无论是HashM…...
【Python】文件 读取 写 os模块 shutil模块 pickle模块
目录 1.文件 1.1 读取操作 1.2 写操作 1.3 os:文件管理 1.4 os.path:获取文件属性 1.5 shutil:文件的拷贝删除移动解压缩 1.6 pickle:数据永久存储 1.文件 文件编码 编码是一种规则集合,记录内容和二进制间相互…...
PAT A1087 All Roads Lead to Rome
1087 All Roads Lead to Rome 分数 30 作者 CHEN, Yue 单位 浙江大学 Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness. Input Specific…...
浅谈HttpURLConnection所有方法详解
HttpURLConnection 类是 Java 中用于实现 HTTP 协议的基础类,它提供了一系列方法来建立与 HTTP 服务器的连接、发送请求并读取响应信息。下面是 HttpURLConnection 类中常用的方法以及其详细解释: ---------------------------------------------------…...
前端快速创建web3应用模版分享
一、起因 一直以来都有一个创建前端Dapp模版的愿望,一来是工作中也有这样的需要,避免每次都要抽离重复的代码。二来是这样的模版也能帮助其他前端快速了解到web3应用的脚手架以及框架结构。于是决定整理一个模版并开源,希望我的代码能帮助到大…...
越权漏洞讲解
越权漏洞是指系统或应用程序中存在的安全漏洞,允许攻击者以超越其授权范围的方式访问系统资源或执行特权操作。这种漏洞可能会导致严重的安全风险,因为攻击者可以利用它来获取敏感信息、修改系统设置或执行恶意操作。 下面是一些常见的越权漏洞类型和它…...
短视频矩阵源码系统打包.源码
Masayl是一款基于区块链技术的去中心化应用程序开发平台,可帮助开发者快速、便捷地创建去中心化应用程序。Masayl拥有丰富的API和SDK,为开发者们提供了支持。此外,Masayl还采用了高效的智能合约技术,确保应用程序的稳定、安全和高…...
云南LED、LCD显示屏系统建设,户外、室内广告大屏建设方案
LED大屏幕显示系统是LED高清晰数字显示技术、显示单元无缝拼接技术、多屏图像处理技术、信号切换技术、网络技术等科技手段的应用综合为一体,形成一个拥有高亮度、高清晰度、技术先进、功能强大、使用方便的大屏幕投影显示系统。通过大屏幕显示系统,可以…...
Shell脚本:expect脚本免交互
Shell脚本:expect脚本免交互 expect脚本免交互 一、免交互基本概述:1.交互与免交互的区别:2.格式:3.通过read实现免交互:4.通过cat实现查看和重定向:5.变量替换: 二、expect安装:1.…...
王道考研计算机网络第二章知识点汇总
2.1.1物理层基本概念 电气特性和功能特性易混淆,注意区分。电气特性一般指的是某个范围,功能特性一般指的是电平所代表的含义。 2.1.2数据通信基础知识 同步传输是指发送方和接收方节奏是统一的,数据之间是没有间隔的是一个一个的区块。在键…...
06.05
1.二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 考虑一个最朴素的方法:先将 aaa 和 bbb 转化成十进制数,求和后再转化为二进制数。利用 Python 和 Java 自带的高精度运算,我们可以很简单地写出这…...
【虹科案例】虹科数字化仪在激光雷达大气研究中的应用
01 莱布尼茨研究所使用激光雷达进行大气研究 图 1:在 Khlungsborn 的 IAP 办公室测试各种激光器 大气研究使用脉冲激光束通过测量大气中 100 公里高度的多普勒频移和反向散射光来测量沿光束的温度和风速。返回的光信号非常微弱,会被阳光阻挡,…...
Java抽象类介绍
1 问题 声明一个名为Employee的抽象类,其中包含name(姓名)和sex(性别)两个String类型的私有属性,并声明一个继承于Employee抽象类的子类Teacher。 2 方法 2.1 定义一个抽象类:Employee。 2.2 为Employee类设计一个抽象方法。 2.3实现抽象类Em…...
适配器模式的运用
文章目录 一、适配器模式的运用1.1 介绍1.2 适配器模式结构1.3 类适配器模式1.3.1 类适配器模式类图1.3.2 代码 1.4 对象适配器模式1.4.1 对象适配器模式类图1.4.2 代码 1.5 应用场景1.6 JDK源码解析1.6.1 字节流到字符流的转换类图1.6.2 部分源码分析1.6.3 总结 一、适配器模式…...
2023/6/8总结
MySQL必知必会 commit 和 rollback 的差异是commit会提交,而rollback不会,就好像是撤回。 使用保留点: 简单的rollback和commit语句就可以写入或者撤销整个事务处理,但是,只是对简单的事务处理才能这样做࿰…...
AIGC大模型之——以文生图介绍
一、什么是以文生图? 以文生图是AIGC ( AI Generated Content )框架中的一个关键技术,通过文字描述,将文字转化为图像并展示出来。以文生图具有白动化程度高、精度高、可扩展性强、可定制化等优势,具有广泛的应用前景&…...
kali学习笔记(二)
一、关闭自动锁屏 关闭自动锁屏对于测试人员来说,可以按照自己的习惯来设置,不然kali会过十分钟就锁屏,有的时候会比较不方便。 1、使用root账号登录,在display设置选项中做如下设置。 2、把休眠选项关掉。 二、创建快照 关机创…...
avx指令集判断的坑
(一)背景 项目中依赖算法同学编写的算法模块,他们在使用avx,sse指令集来提高速度,结果在一些机器上崩溃,导致项目无法发版。 我给他们说,我们项目中使用了谷歌的 libyuv 库,也使用了…...
求内推,求明主!
个人资料: 性 别: 男 年 龄: 30岁 户 籍: 湖南衡阳 专 业: 计算机科学与技术 求职意向: Java软件开发工程师/JavaWeb开发工程师 现 居 地: 深圳市龙华新区 自考本科学历,6年工作经验(做过商城,APP,小程序,也研究多个开源案例,开源项目,并提交过PR) 自我评价: 做事积极主动,有责…...
第十三章:约束
第十三章:约束 13.1:约束(constraint)概述 为什么需要约束 数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。 为…...
M.2 SSD接口详解
一、M.2简介 M.2接口是一种新的主机接口方案,可以兼容多种通信协议,如sata、PCIe、USB、HSIC、UART、SMBus等。 M.2接口是为超极本(Ultrabook)量身定做的新一代接口标准,以取代原来的mSATA接口。无论是更小巧的规格尺…...
在本地Windows 11 系统的桌面版Docker上搭建PlantUML
文章目录 在本地Windows系统的桌面版Docker上搭建PlantUML简介步骤步骤 1:安装Docker Desktop步骤 2:启动Docker Desktop步骤 3:拉取PlantUML镜像步骤 4:运行PlantUML容器步骤 5:访问PlantUML Web界面 结论参考资料 结…...
mysql的sql_mode模式
1、sql_mode是MySQL中的一个系统变量,用于设置服务器在执行SQL语句时的行为模式。它可以控制服务器的严格性和特性,包括数据校验、日期处理、空值处理等。 下面是一些常见的sql_mode模式及其作用: STRICT_ALL_TABLES:为所有存储…...
chatgpt赋能python:Python编程必备之OpenCV库下载与安装
Python编程必备之OpenCV库下载与安装 作为目前最热门的计算机视觉库之一,OpenCV在人工智能领域中发挥着巨大的作用。而Python作为一门强大的编程语言,在OpenCV的使用上也有其独特的优势。本文将介绍Python如何下载和安装OpenCV库,以及如何引…...
wordpress后台打开缓慢/seo优化关键词放多少合适
点击查看全文 根据Stack Overflow流量分析了Python及其他一些编程语言的发展情况,同时也对高收入国家与非高收入国家的情况进行了对比。 我们最近的研究表明,富裕国家(世界银行定义为高收入国家)喜欢研究的技术与其他国家的不同。…...
网站营销推广方案/网络广告的优势有哪些
本文主要内容:1 ElasticSearch常用的操作2 ElasticSearchbulk命令ES REST APIelasticsearch支持多种通讯,其中包括http请求响应服务,因此通过curl命令,可以发送http请求,并得到json返回内容。常用的REST请求有…...
网站建设的总体目标/青岛新闻最新今日头条
在用vue做 移动端项目的时候. 特别是调用相机拍照的时候有些手机会旋转照片,导致拍出来是 歪的, 横着的, 这里记录下怎么解决这个问题. demo 请狠狠的戳这里 https://download.lllomh.com/cliect/#/product/A810032847082261 1, 安装 compressorjs 插件,导入 import Comp…...
无锡快速建设网站方法/百度网站推广一年多少钱
• 向指定的txt文件中写入键盘输入的内容,然后再重新读取该文件的内容,显示到控制台上。 • 键盘录入5个学生信息(姓名, 成绩),按照成绩从高到低存入文本文件。 package 复习第七章作业第四答题;import java.io.*; import java.util.*;publ…...
网站建设管理与政府/百度竞价怎么开户
文章目录1. 自定义登录页面2. 关闭csrf token参考相关文章: Spring Security默认登录页面原理 spring security 自定义登录页面 1. 自定义登录页面 核心是通过配置,覆盖原有默认的登陆页面: //不写这个注解配置不生效 Configuration publi…...
做网站和做网店哪个好/企业网站建设推广
premiere软件功能很丰富,但是如果只是做个教程这种程度的简单剪辑用到的功能是非常少的。在这里做个笔记,免的之后又忘记怎么操作premiere 制作文件保存的时候不会保存原始视频。所以原始视频一定要找专门的文件夹放,免的后期误删,…...