java线程池的使用
Java concurrency线程池之线程池原理(三)

Java concurrency线程池之线程池原理(三)线程有5种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态。
线程池也有5种状态;然而,线程池不同于线程,线程池的5种状态是:Running, SHUTDOWN, STOP, TIDYING, TERMINATED。
线程池状态定义代码如下:private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));private static final int COUNT_BITS = Integer.SIZE - 3;private static final int CAPACITY = (1 << COUNT_BITS) - 1;private static final int RUNNING = -1 << COUNT_BITS;private static final int SHUTDOWN = 0 << COUNT_BITS;private static final int STOP = 1 << COUNT_BITS;private static final int TIDYING = 2 << COUNT_BITS;private static final int TERMINATED = 3 << COUNT_BITS;private static int ctlOf(int rs, int wc) { return rs | wc; }说明:ctl是一个AtomicInteger类型的原子对象。
ctl记录了"线程池中的任务数量"和"线程池状态"2个信息。
ctl共包括32位。
其中,高3位表示"线程池状态",低29位表示"线程池中的任务数量"。
Java自定义线程池的实现示例

Java⾃定义线程池的实现⽰例⽬录⼀、Java语⾔本⾝也是多线程,回顾Java创建线程⽅式如下:⼆、JDK线程池⼯具类.三、业界知名⾃定义线程池扩展使⽤.⼀、Java语⾔本⾝也是多线程,回顾Java创建线程⽅式如下:1、继承Thread类,(Thread类实现Runnable接⼝),来个类图加深印象。
2、实现Runnable接⼝实现⽆返回值、实现run()⽅法,啥时候run,⿊话了。
3、实现Callable接⼝重写call()+FutureTask获取.public class CustomThread {public static void main(String[] args) {// ⾃定义线程new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Custom Run");System.out.println(Thread.currentThread().getName());}},"custom-thread-1").start();}}4、基于线程池集中管理创建线程系列周期.【本篇⽂章重点介绍】⼆、JDK线程池⼯具类.1、Executors⼯具类,是JDK中Doug Lea⼤佬实现供开发者使⽤。
随着JDK版本迭代逐渐加⼊了基于⼯作窃取算法的线程池了,阿⾥编码规范也推荐开发者⾃定义线程池,禁⽌⽣产直接使⽤Executos线程池⼯具类,因此很有可能造成OOM异常。
同时在某些类型的线程池⾥⾯,使⽤⽆界队列还会导致maxinumPoolSize、keepAliveTime、handler等参数失效。
因此⽬前在⼤⼚的开发规范中会强调禁⽌使⽤Executors来创建线程池。
这⾥说道阻塞队列。
LinkedBlockingQueue。
2、⾃定义线程池⼯具类基于ThreadPoolExecutor实现,那个JDK封装的线程池⼯具类也是基于这个ThreadPoolExecutor实现的。
newcachedthreadpool详解

newcachedthreadpool详解在Java 中,`newCachedThreadPool` 是`Executors` 工具类提供的一个静态方法,用于创建一个根据需要创建新线程的线程池。
该线程池在执行任务时,会尽可能地重用之前构造的线程,如果线程不存在,将创建一个新线程。
如果一个线程在60秒内没有被使用,它将被终止并从缓存中移除。
这使得该线程池适用于执行大量生存期很短的异步任务。
以下是`newCachedThreadPool` 方法的基本用法和一些相关的详解:```javaimport java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CachedThreadPoolExample {public static void main(String[] args) {// 创建一个缓存线程池ExecutorService executorService = Executors.newCachedThreadPool();// 提交任务给线程池for (int i = 0; i < 10; i++) {final int taskId = i;executorService.execute(() -> {System.out.println("Task " + taskId + " executed by thread: " + Thread.currentThread().getName());});}// 关闭线程池executorService.shutdown();}}```上述代码演示了如何使用`newCachedThreadPool` 方法创建一个缓存线程池。
关键点如下:1. 创建线程池:使用`Executors.newCachedThreadPool()` 方法创建一个缓存线程池。
java定时器线程池(ScheduledThreadPoolExecutor)的实现

java定时器线程池(ScheduledThreadPoolExecutor)的实现前⾔定时器线程池提供了定时执⾏任务的能⼒,即可以延迟执⾏,可以周期性执⾏。
但定时器线程池也还是线程池,最底层实现还是ThreadPoolExecutor,可以参考我的另外⼀篇⽂章多线程–精通ThreadPoolExecutor。
特点说明1.构造函数public ScheduledThreadPoolExecutor(int corePoolSize) {// 对于其他⼏个参数在ThreadPoolExecutor中都已经详细分析过了,所以这⾥,将不再展开// 这⾥我们可以看到调⽤基类中的⽅法时有个特殊的⼊参DelayedWorkQueue。
// 同时我们也可以发现这⾥并没有设置延迟时间、周期等参数⼊⼝。
// 所以定时执⾏的实现必然在DelayedWorkQueue这个对象中了。
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}2.DelayedWorkQueueDelayedWorkQueue是在ScheduledThreadPoolExecutor的⼀个内部类,实现了BlockingQueue接⼝⾥⾯存放任务队列的数组如下:private RunnableScheduledFuture<?>[] queue =new RunnableScheduledFuture<?>[INITIAL_CAPACITY];我们分析过ThreadPoolExecutor,它从任务队列中获取任务的⽅式为poll和take两种,所以看⼀下poll和take两个⽅法的源码,回顾⼀下,ThreadPoolExecutor它会调⽤poll或take⽅法,先poll,再take,只要其中⼀个接⼝有返回就⾏public RunnableScheduledFuture<?> poll() {final ReentrantLock lock = this.lock;lock.lock();try {RunnableScheduledFuture<?> first = queue[0];// 这⾥有个getDelay,这是关键点,获取执⾏延时时间// 但是如果我们有延时设置的话,这就返回空了,然后就会调⽤take⽅法if (first == null || first.getDelay(NANOSECONDS) > 0)return null;elsereturn finishPoll(first);} finally {lock.unlock();}}public RunnableScheduledFuture<?> take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {RunnableScheduledFuture<?> first = queue[0];if (first == null)available.await();else {// 获取延时时间long delay = first.getDelay(NANOSECONDS);if (delay <= 0)return finishPoll(first);first = null; // don't retain ref while waitingif (leader != null)available.await();else {Thread thisThread = Thread.currentThread();leader = thisThread;try {// 使⽤锁,执⾏延时等待。
java 中 线程按照顺序执行的方法

Java 中线程按照顺序执行的方法在 Java 编程中,线程按照顺序执行是非常重要的,特别是在涉及到多线程并发操作的情况下。
在本文中,我将为您详细介绍在 Java 中实现线程按照顺序执行的方法,从简单的基础概念到更深入的技巧,让您更全面、深刻理解这一重要主题。
1. 使用 join() 方法在 Java 中,可以使用 join() 方法来实现线程按照顺序执行。
当一个线程调用另一个线程的 join() 方法时,它会等待该线程执行完毕。
这种方式可以保证线程的执行顺序,但需要注意 join() 方法的调用顺序和逻辑,以避免死锁等问题。
2. 使用 CountDownLatch 类CountDownLatch 是 Java 并发包中提供的一个工具类,它可以让一个或多个线程等待其他线程的完成。
通过适当使用CountDownLatch,可以实现线程按照顺序执行的效果,确保在某个线程执行完毕后再执行下一个线程。
3. 使用 Lock 和 ConditionJava 中的 Lock 和 Condition 是用于替代 synchronized 和wait/notify 的高级并发工具。
通过使用 Lock 和 Condition,可以实现更灵活和精确的线程控制,从而实现线程按照顺序执行。
4. 使用线程池线程池是 Java 中用于管理和复用线程的机制,通过合理配置线程池的参数和任务队列,可以确保线程按照一定顺序执行。
在实际开发中,合理使用线程池可以提高程序的性能和可维护性。
总结回顾通过使用 join() 方法、CountDownLatch、Lock 和 Condition、以及线程池等方法,可以实现线程按照顺序执行的效果。
在实际开发中,需要根据具体的业务需求和场景来选择合适的方法,同时要注意线程安全和性能等问题。
个人观点和理解在我看来,线程按照顺序执行是多线程编程中的一个重要问题,它涉及到了线程安全、并发控制和性能优化等方面的知识。
java 中线程池的几个参数

java 中线程池的几个参数
Java中线程池的几个参数包括:
1. corePoolSize:线程池的核心线程数,即线程池中一直保持
的线程数量,即使线程处于空闲状态。
2. maximumPoolSize:线程池的最大线程数,即线程池中允许
存在的最大线程数量。
3. keepAliveTime:线程在空闲状态下的存活时间,当线程池
中的线程数量超过corePoolSize时,如果空闲线程超过指定时
间则会被终止。
4. unit:keepAliveTime的时间单位,可以是毫秒、秒、分钟等。
5. workQueue:用于保存等待执行的任务的阻塞队列,当任务
数量超过核心线程数时,新增的任务会被添加到该队列中等待执行。
6. threadFactory:用于创建新线程的工厂。
7. handler:当线程池已满且阻塞队列已满时,用于处理新提交的任务的拒绝策略,可以是抛出异常、丢弃任务等。
这些参数可以通过ThreadPoolExecutor类的构造方法进行设置,例如:
```
ThreadPoolExecutor executor = new
ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
```。
6、java5线程池之固定大小线程池newFixedThreadPool
6、java5线程池之固定⼤⼩线程池newFixedThreadPoolJDK⽂档说明:创建⼀个可重⽤固定线程数的线程池,以共享的⽆界队列⽅式来运⾏这些线程。
在任意点,在⼤多数 nThreads 线程会处于处理任务的活动状态。
如果在所有线程处于活动状态时提交附加任务,则在有可⽤线程之前,附加任务将在队列中等待。
如果创建⽅法:java.util.concurrent.Executors.newFixedThreadPool(int nThreads)orjava.util.concurrent.Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory)调⽤上⾯2个⽅法得到的对象为:ExecutorServiceJDK⾃带的例⼦:下⾯给出了⼀个⽹络服务的简单结构,这⾥线程池中的线程作为传⼊的请求。
它使⽤了预先配置的Executors.newFixedThreadPool(int)⼯⼚⽅法:class NetworkService implements Runnable {private final ServerSocket serverSocket;private final ExecutorService pool;public NetworkService(int port, int poolSize) throws IOException {serverSocket = new ServerSocket(port);pool = Executors.newFixedThreadPool(poolSize);}public void run() { // run the servicetry {for (;;) {pool.execute(new Handler(serverSocket.accept()));}} catch (IOException ex) {pool.shutdown();}}}class Handler implements Runnable {private final Socket socket;Handler(Socket socket) { this.socket = socket; }public void run() {// read and service request on socket}}主要的⽅法:boolean awaitTermination(long timeout, TimeUnit unit)请求关闭、发⽣超时或者当前线程中断,⽆论哪⼀个⾸先发⽣之后,都将导致阻塞,直到所有任务完成执⾏。
java 对象池 使用场景
java 对象池使用场景Java对象池的使用场景随着互联网的快速发展和技术的不断进步,Java作为一种高性能、跨平台的编程语言,被广泛应用于各个领域。
在Java开发中,对象池是一种常见的设计模式,它可以提高系统的性能和资源利用率,以下是几个常见的使用场景。
1. 数据库连接池在Java开发中,数据库是一个非常重要的组件,而数据库连接是与数据库进行交互的基本单位。
为了提高系统的性能,我们可以使用对象池来管理数据库连接。
通过预先创建一定数量的数据库连接对象,并将其保存在对象池中,当系统需要使用数据库连接时,直接从对象池中获取,使用完毕后再将其归还给对象池,这样可以避免频繁创建和销毁数据库连接对象,提高系统的性能和效率。
2. 线程池在多线程编程中,线程是一种非常重要的资源,频繁地创建和销毁线程会消耗大量的系统资源,降低系统的性能。
为了提高系统的并发性和资源利用率,可以使用对象池来管理线程。
通过预先创建一定数量的线程对象,并将其保存在对象池中,当系统需要执行任务时,直接从对象池中获取一个空闲线程,执行完任务后再将线程归还给对象池,这样可以避免频繁创建和销毁线程,提高系统的并发性和资源利用率。
3. 连接池在网络编程中,连接是与服务器进行通信的基本单位。
为了提高系统的性能和效率,可以使用对象池来管理连接。
通过预先创建一定数量的连接对象,并将其保存在对象池中,当系统需要与服务器建立连接时,直接从对象池中获取一个空闲连接,使用完毕后再将其归还给对象池,这样可以避免频繁创建和销毁连接对象,提高系统的性能和效率。
4. 对象缓存在某些场景下,某种对象的创建和销毁是非常耗时的,为了提高系统的性能和效率,可以使用对象池来管理这种对象。
通过预先创建一定数量的对象,并将其保存在对象池中,当系统需要使用该对象时,直接从对象池中获取,使用完毕后再将其归还给对象池,这样可以避免频繁创建和销毁对象,提高系统的性能和效率。
5. 资源池除了前面提到的数据库连接池、线程池和连接池,还有很多其他类型的资源可以使用对象池进行管理,比如文件句柄、网络连接等。
浅谈Java线程池的7大核心参数
浅谈Java线程池的7⼤核⼼参数⽬录前⾔⼀、线程池的创建及重要参数⼆、ThreadPoolExecutor中重要的⼏个参数详解三、workQueue队列(阻塞队列)四、常见的⼏种⾃动创建线程池⽅式五、线程池实现线程复⽤的原理六、⼿动创建线程池(推荐)七、Springboot中使⽤线程池前⾔java中经常需要⽤到多线程来处理⼀些业务,我不建议单纯使⽤继承Thread或者实现Runnable接⼝的⽅式来创建线程,那样势必有创建及销毁线程耗费资源、线程上下⽂切换问题。
同时创建过多的线程也可能引发资源耗尽的风险,这个时候引⼊线程池⽐较合理,⽅便线程任务的管理。
java中涉及到线程池的相关类均在jdk1.5开始的java.util.concurrent包中,涉及到的⼏个核⼼类及接⼝包括:Executor、Executors、ExecutorService、ThreadPoolExecutor、FutureTask、Callable、Runnable等。
⼀、线程池的创建及重要参数线程池可以⾃动创建也可以⼿动创建,⾃动创建体现在Executors⼯具类中,常见的可以创建newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool;⼿动创建体现在可以灵活设置线程池的各个参数,体现在代码中即ThreadPoolExecutor类构造器上各个实参的不同:public static ExecutorService newFixedThreadPool(int var0) {return new ThreadPoolExecutor(var0, var0, 0L, LISECONDS, new LinkedBlockingQueue());}public static ExecutorService newSingleThreadExecutor() {return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, LISECONDS, new LinkedBlockingQueue()));}public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());}public static ScheduledExecutorService newScheduledThreadPool(int var0) {return new ScheduledThreadPoolExecutor(var0);}(重点)public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {……}⼆、ThreadPoolExecutor中重要的⼏个参数详解corePoolSize:核⼼线程数,也是线程池中常驻的线程数,线程池初始化时默认是没有线程的,当任务来临时才开始创建线程去执⾏任务maximumPoolSize:最⼤线程数,在核⼼线程数的基础上可能会额外增加⼀些⾮核⼼线程,需要注意的是只有当workQueue队列填满时才会创建多于corePoolSize 的线程(线程池总线程数不超过maxPoolSize)keepAliveTime:⾮核⼼线程的空闲时间超过keepAliveTime就会被⾃动终⽌回收掉,注意当corePoolSize=maxPoolSize时,keepAliveTime参数也就不起作⽤了(因为不存在⾮核⼼线程);unit:keepAliveTime的时间单位workQueue:⽤于保存任务的队列,可以为⽆界、有界、同步移交三种队列类型之⼀,当池⼦⾥的⼯作线程数⼤于corePoolSize时,这时新进来的任务会被放到队列中threadFactory:创建线程的⼯⼚类,默认使⽤Executors.defaultThreadFactory(),也可以使⽤guava库的ThreadFactoryBuilder来创建handler:线程池⽆法继续接收任务(队列已满且线程数达到maximunPoolSize)时的饱和策略,取值有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy线程池中的线程创建流程图:(基于<Java并发编程的艺术>⼀书)举个例⼦:现有⼀个线程池,corePoolSize=10,maxPoolSize=20,队列长度为100,那么当任务过来会先创建10个核⼼线程数,接下来进来的任务会进⼊到队列中直到队列满了,会创建额外的线程来执⾏任务(最多20个线程),这个时候如果再来任务就会执⾏拒绝策略。
executors.newsinglethreadexecutor 用法
executors.newsinglethreadexecutor 用法什么是`Executors.newSingleThreadExecutor`?`Executors.newSingleThreadExecutor` 是Java 中的一个线程池工具类,它是通过`Executors` 类的静态方法所提供的,用于创建一个只有一个线程的线程池。
这个线程池可以执行提交的任务,并按照提交的顺序来执行它们。
当一个任务执行完成后,线程池会接收、处理并执行下一个任务。
为什么要使用`Executors.newSingleThreadExecutor`?在应用程序中,有许多场景需要按顺序执行一连串的任务。
使用线程池可以帮助我们在执行这些任务时更好地管理线程的创建和销毁过程,从而提升应用程序的性能和效率。
对于需要按顺序执行一系列任务的场景,单线程池是一个非常合适的选择。
因为单线程池只有一个线程,所以能够保证任务的执行顺序不会出现并发的问题。
这种保证任务按顺序执行的能力,在某些情况下非常重要,比如在处理一些需要遵循先后顺序的事件时,或者在进行某些独占资源的操作时。
如何使用`Executors.newSingleThreadExecutor`?使用`Executors.newSingleThreadExecutor` 创建一个单线程池非常简单,只需要调用该方法即可。
下面是一步一步的方法:1. 导入所需的类和包。
javaimport java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;2. 调用`Executors.newSingleThreadExecutor` 方法创建一个单线程池。
javaExecutorService executor = Executors.newSingleThreadExecutor();3. 创建一个任务,可以是`Runnable` 或`Callable` 对象。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java线程池的使用
1.4版本JDK线程池的代替
定义一个线程( TimerTask )
public class TimerTestTask extends TimerTask {
private String name="";
public TimerTestTask(String name){
this.name=name;
}
public void run() {
for(int i=0;i<10;i+=1){
System.out.println("第"+i+"个-"+name+"-说:你好");
}
}
}
使用线程池调用( Timer )
public static void main(String[] args){
TimerTestTask tsk1=new TimerTestTask("小明");
TimerTestTask tsk2=new TimerTestTask("小红");
TimerTestTask tsk3=new TimerTestTask("笨笨");
TimerTestTask tsk4=new TimerTestTask("贝贝");
TimerTestTask tsk5=new TimerTestTask("呆呆");
Timer timer=new Timer();
timer.schedule(tsk1,0L);
timer.schedule(tsk2,0L);
timer.schedule(tsk3,0L);
timer.schedule(tsk4,0L);
timer.schedule(tsk5,0L);
System.out.println("完成");
}
以下所使用的线程池功能必须在1.5JDK以上版本才能使用;
Executors.newFixedThreadPool - 固定数量的线程池
一个线程池是一批线程的操作容器;(例如:停车厂)
创建一个固定可用线程数量的线程池(newFixedThreadPool),线程池这东西不会因为投放的
数量过多,而自己没有足够的空闲线程报错;
同一时刻同时处理任务的线程越多,则平均性能越差,如果固定线程池配置线程数量为1
则每个线程的执行效率很高。
同时创建多个线程池处理任务,性能会有很大影响吗?
一个线程池内的多个线程同时处理,性能上会有影响,但是A线程池内的线程,对B线程
池内的线程性能上不会有影响。
FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建
线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会
释放工作线程,还会占用一定的系统资源。
定义一个线程
public class ThreadTestRunnable implements Runnable {
public String name;
public ThreadTestRunnable(String name){
this.name=name;
}
public void run() {
long lStart=(new Date()).getTime();
String s="";
for(int i=0;i<5000;i+=1){
s+="aabc";
}
long lEnd=(new Date()).getTime();
System.out.println( name+"-执行完成:"+(lEnd-lStart) );
}
}
使用线程池调用
//创建线程池A
ExecutorService execu = Executors.newFixedThreadPool(6);
execu.execute(th1);
execu.execute(th2);
execu.execute(th3);
execu.execute(th4);
execu.execute(th5);
execu.execute(th6);
execu.shutdown();
//创建线程池B
execu = Executors.newFixedThreadPool(1);
execu.execute(th1a);
execu.execute(th2a);
execu.execute(th3a);
execu.execute(th4a);
execu.execute(th5a);
execu.execute(th6a);
execu.shutdown();
Executors.newSingleThreadExecutor - 单线线程池
只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺
序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并
且在任意给定的时间不会有多个线程是活动的 。
使用线程池
Thread th1=new Thread(new ThreadTestRunnable("小明"));
ExecutorService execu = Executors.newSingleThreadExecutor();
execu.execute(th1); //启动
execu.shutdown(); //关闭
Executors.newCachedThreadPool - 缓存线程池
工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这
样可灵活的往线程池中添加线程。
如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分
钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一
个工作线程。
线程池空闲时,即线程池中没有可运行任务时,它会释放工作线程,从而释放工作线程
所占用的资源。但是,但当出现新任务时,又要创建一新的工作线程,又要一定的系统开销。
并且,在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同
时运行,很有会造成系统瘫痪。
使用线程池
ExecutorService execu = Executors.newCachedThreadPool();
execu.execute(th1);
execu.execute(th2);
execu.shutdown();
newScheduleThreadPool - 定长线程池
略