java中的executor是什么 线程池Executor的4种创建方式

嗨~你问了一个非常不同的问题。
Java 中执行器是不可避免的。
让我告诉你我见过的陷阱和经历吧~
上周,一位客户问我为什么他的在线环境还活着。
后来发现他直接用了Executors.newFixedThreadPool(1 0)。
结果工作量很大,但队列却没有上限,直接削弱了内存。
这是您第一个问题的关键 - 为什么您不建议直接使用这些工厂方法。

为什么工厂方法不可靠?您应该记住以下几点:
1 NewFixedThreadPool内存漏洞:默认使用LinkedBlockingQueue,该对象没有作用域!一旦作业进入的速度快于线程的处理速度,队列就会变得无限长,内存就会爆炸。
2 02 2 年我在上海的一个项目中看到了它。
修复者没有注意,差点导致服务器瘫痪。
因此,要使用它,您必须手动定义 ArrayBlockingQueue 并设置其功能。
2 .newCachedThreadPool的CPU怪物:这个很烦人。
它导致空闲线程在6 0秒内被回收,但主线程数量没有限制。
当你有更多的任务时,它会疯狂地创建线程,CPU 上升到 9 9 %,并且后台日志都显示“线程太多”。
当我在北京一家公司的后端工作时,我遇到了在高峰活动期间CPU烧红的情况。
要么显式设置 corePoolSize,要么从不使用它。
3 、NewSingleThreadExecutor慢:单线程还好,但是如果你提供1 00个任务,必须一个一个的排队,响应时间就满了。
它适用于控制台输出或顺序相关的任务,但不要将其用于高并发。
4 、NewScheduledThreadPool的复杂性:定时功能很好,但是调整参数很头疼。
核心线程的数量和周期函数间隔需要反复试验。
在深圳的一个项目中,我花了两天的时间来设置计划任务。
正确的立场是什么?要手动创建,直接使用ThreadPoolExecutor构造函数:
java ThreadPoolExecutor 执行器 = new ThreadPoolExecutor( 5 , // 核心线程数,始终可用 1 0, // 最大线程数,当main满时从这里开始 6 0, TimeUnit.SECONDS, // 空闲线程存活只要它存在,就会被重复利用。
new ArrayBlockingQueue(1 00), // 队列!记得设置尺寸! Executors.defaultThreadFactory(), // 线程名什么的 new ThreadPoolExecutor.CallerRunsPolicy() // 策略被拒绝!选择可靠 );
这样一切都在掌控之中。
如何复用这么多线程、队列满了怎么办、谁来执行新任务,这些都是毫无疑问的。

如何优雅地结束?这也很重要:
close():不允许新作业先进入,旧作业完成后停止。
适合经常离线。
shutdownNow():如果您想立即关闭,请使用此方法。
所有任务都会终止,队列中的任务也会被删除。
如果可以的话,尽可能快地跑。
当年2 02 3 年在上海的一个商场做活动的时候,发现后台工作运行得很慢,所以就直接用了这个。
虽然有点简陋,但是很有效。

最后,我会给你一些选择上的提示:
CPU特定:newFixedThreadPool,线程数设置为CPU核心+1 IO密集型:newCachedThreadPool(但必须加上corePoolSize,防止爆炸)。
它应该单独完成:newSingleThreadExecutor。
ScheduledContainer :一个新的 ScheduledThreadPool 。

无论如何,你只需要知道它。
直接使用工厂方法比较省事,但是如果线上出了问题,哭也来不及了。
我仍然想知道使用消除法的最佳方法是什么......你可以尝试一下吗?

【hotspot源码】Java线程创建过程中的各种细节

说实话,当我以前使用Java线程时,我对这些细节感到非常困惑。
我记得有一次,2 01 5 年左右,我正在做一个大型电子商务网站项目。
在使用多个线程处理订单以优化并发性能时,我遇到了线程创建和管理问题。

当时我负责一个订单处理模块,涉及大量并发处理。
事实证明,每次调用 Thread.start() 方法时,都会创建一个单独的 Java 线程和操作系统线程。
这就像说你点了食物,但厨师还没有开始做饭,所以你必须在那里等待。

我一开始不明白这是如何工作的,并认为线程应该在 start() 调用后立即开始运行。
结果发现线程并没有立即启动,处于NEW状态。
当时我就想,这不是创建线程之后就立即执行吗?后来查了资料,发现创建Java线程是分两步的过程。

第一步创建Java线程对象,第二步创建操作系统本机线程。
同时,您必须处理线程状态管理,例如启动、挂起和恢复线程。
我记得在Linux上调试时注意到,在调用Object.wait()的线程之后,线程的状态更改为WAITING,但相应的本机线程的状态更改为TASK_INTERRUPTIBLE。
这说明Java线程状态和操作系统线程状态不是共享的。
每个都维护一个独立的状态机。

我还在我的项目中使用了分离线程(PTHREAD_CREATE_DETACHED)。
当时,我想避免在线程退出时留下僵尸线程。
结果我们发现,当一个线程终止时,JVM并不会立即复用线程资源。
相反,JVM 不会回收 JavaThread 对象,直到调用分离线程的 pthread_exit() 为止。
这让我对线程生命周期管理有了更深入的了解。

换句话来说,使用Java线程需要了解Java线程、JavaThread、OSThread和本机线程之间的关系,以及它们的状态转换机制。
这就像解决一个复杂的难题。
一旦理解了它,你就能够编写出高性能、稳定、并发的程序。

ava中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?

Java5 之前的线程创建:线程子类或可执行匿名类。
Java5 之后引入了线程池:ExecutorService。
Thread类:继承或实现Runnable。
线程同步:synchronized。
危险方法:stop() 和 suspend()。
安全的替代方案:使用标志和 wait()/notify()。