java中线程池的使用,java线程池好处

java中线程池的使用,java线程池好处,Java 线程池的作用以及该如何使用

本文主要介绍Java线程池的功能和使用方法,帮助您更好地理解和学习Java的相关知识。感兴趣的朋友可以了解一下。

服务器端应用程序(如数据库和Web服务器)需要处理来自客户端的高并发和耗时短的请求,因此频繁创建处理这些请求所需的线程是一项非常消耗资源的操作。传统的方法是为新请求创建一个新线程。尽管这种方法看起来很容易实现,但它有明显的缺点。为每个请求创建一个新线程需要更多的时间,创建和销毁线程需要更多的系统资源。所以同时创建太多线程的JVM可能会导致系统内存不足,这就需要限制要创建的线程数量,也就是使用线程池。

一、Java中的线程池是什么?

线程池技术(Thread pool technology)是线程的重用技术,它使用先前创建的线程来执行当前任务,并为线程周期开销和资源冲突问题提供解决方案。因为请求到达时线程已经存在,所以消除了线程创建过程造成的延迟,应用程序获得了更快的响应。

Java提供了一个以executor接口及其子接口ExecutorService和ThreadPoolExecutor为中心的Executor框架。通过使用执行器,完成线程任务,只需要实现Runnable接口,交给执行器执行即可。

为你封装线程池,让你的编程任务专注于具体任务的实现,而不是线程的实现机制。

为了使用线程池,我们首先创建一个ExecutorService对象,然后向它传递一组任务。ThreadPoolExcutor类可以设置线程池的初始化和最大线程容量。

上图显示线程池初始化中有三个线程,任务队列中有五个任务对象要运行。

执行器线程池方法

方法

形容

newFixedThreadPool(int)

创建一个线程数量固定的线程池,int参数表示线程池中的线程数量。

newCachedThreadPool()

创建一个可缓存的线程池,可以灵活回收空闲线程。如果没有空闲线程,则创建一个新的线程处理任务。

newSingleThreadExecutor()

创建单线程线程池,该线程池将只使用唯一的工作线程来执行任务。

新计划线程池

创建一个固定长度的线程池来支持计划的和定期的任务执行。

在固定线程池的情况下,如果所有当前正在运行的线程都被执行,那么挂起的任务将被放入队列中,并在线程空闲时执行。

二。线程池示例

在下面的内容中,我们将介绍线程池的执行器。

创建线程池处理任务要遵循的步骤

创建一个任务对象(实现Runnable接口)来执行特定的任务逻辑。

使用执行器创建线程池执行器服务

将要执行的任务对象交给ExecutorService进行任务处理。

停止执行器线程池

//步骤1:创建一个任务对象(实现Runnable接口)来执行特定的任务逻辑(步骤1)

类任务实现Runnable {

私有字符串名称;

公共任务(字符串){

name=s;

}

//打印任务名称并休眠1秒钟

//整个过程执行5次。

公共无效运行(){

尝试{

for(int I=0;I=5;i ) {

if (i==0) {

日期d=新日期();

simple date format ft=new simple date format(' hh:mm:ss ');

System.out.println('任务初始化' name '=' ft . format(d));

//第一次执行时打印每个任务的名称和初始化时间。

}

否则{

日期d=新日期();

simple date format ft=new simple date format(' hh:mm:ss ');

System.out.println ('task正在执行' name '=' ft . format(d));

//打印每个任务处理的执行时间。

}

thread . sleep(1000);

}

System.out.println('任务执行完成'名称);

} catch(InterruptedException e) {

e . printstacktrace();

}

}

}

判例案件

公共类ThreadPoolTest {

//线程池中的最大线程数

static final int MAX _ SIZE=3;

公共静态void main (String[] args) {

//创建5个任务

Runnable r1=新任务('任务1 ');

Runnable r2=新任务('任务2 ');

Runnable r3=新任务('任务3 ');

Runnable r4=新任务('任务4 ');

Runnable r5=新任务('任务5 ');

//第二步:创建一个线程数量固定的线程池,线程数量为MAX_SIZE

ExecutorService pool=executors . newfixedthreadpool(MAX _ SIZE);

//第三步:将要执行的任务对象交给ExecutorService进行任务处理。

pool . execute(R1);

pool . execute(R2);

pool . execute(R3);

pool . execute(R4);

pool . execute(r5);

//步骤4:关闭线程池

pool . shut down();

}

}

示例执行结果

初始化任务任务1=05:25:55

初始化任务任务2=05:25:55

任务初始化任务3=05:25:55

正在执行任务任务3=05:25:56

任务正在执行任务1=05:25:56

任务正在执行任务2=05:25:56

该任务正在执行任务1=05:25:57

正在执行任务任务3=05:25:57

任务正在执行任务2=05:25:57

正在执行任务任务3=05:25:58

该任务正在执行任务1=05:25:58

任务正在执行任务2=05:25:58

该任务正在执行任务2=05:25:59

正在执行任务任务3=05:25:59

任务正在执行任务1=05:25:59

任务正在执行任务1=05:26:00

任务正在执行任务2=05:26:00

任务正在执行任务3=05:26:00

任务执行已完成任务3

任务执行已完成任务2

任务执行已完成任务1

初始化任务任务5=05:26:01

初始化任务任务4=05:26:01

任务正在执行任务4=05:26:02

任务正在执行任务5=05:26:02

任务正在执行任务4=05:26:03

任务正在执行任务5=05:26:03

任务正在执行任务5=05:26:04

任务正在执行任务4=05:26:04

任务正在执行任务4=05:26:05

任务正在执行任务5=05:26:05

任务正在执行任务4=05:26:06

任务正在执行任务5=05:26:06

任务执行已完成任务4

任务执行已完成任务5

如程序执行结果所示,只有当池中的线程空闲时,才会执行任务4或任务5。在此之前,其他任务将被放在队列中等待执行。

线程池执行前三个任务,线程池中的线程被回收,然后被处理执行任务4和5。

使用这种线程池方法的一个主要优点是,如果你想一次处理10,000个请求,但又不想创建10,000个线程,这样可以避免过度使用系统资源导致的停机。您可以使用这个方法创建一个包含500个线程的线程池,并向线程池提交500个请求。

ThreadPool将创建多达500个线程,一次处理500个请求。任何线程的进程完成后,ThreadPool将在内部将第501个请求分配给该线程,并继续对所有剩余的请求执行相同的操作。在系统资源紧张的情况下,线程池是保证程序稳定运行的有效解决方案。

三、线程池的使用注意事项和调优

死锁(Deadlock ):虽然任何多线程程序中都可能发生死锁,但线程池会引入另一种死锁情况,即所有正在执行的线程都在等待队列中某个被阻塞线程的执行结果,导致该线程无法继续执行。

线程泄漏:如果任务完成时线程池中的线程没有正确返回,就会出现线程泄漏问题。例如,如果一个线程抛出了一个异常,而池类未能捕捉到它,那么该线程将异常退出,线程池的大小将减少一。如果这种情况重复多次,线程池最终会变空,没有线程可用于执行其他任务。

频繁的线程轮换:如果线程池非常大,在线程之间切换上下文会浪费很多时间。所以在系统资源允许的情况下,线程池越大越好。

线程池大小优化:线程池的最佳大小取决于可用处理器的数量和挂起任务的性质。对于CPU密集型任务,假设系统有N个逻辑处理核心,最大数量为N或N-1的线程池将实现最高效率。对于I/O密集型任务,应该考虑请求的等待时间(W)与服务的处理时间(S)的比值,N*(1 W/S)的最大线程池大小将实现最高的效率。

不要教条式的使用上面的总结,需要根据自己的应用任务处理类型进行灵活的设置和调优,其中测试实验必不可少。

原文链接:字母表博客。

以上是Java线程池的作用和使用方法的详细介绍。关于Java线程池的作用和使用的更多信息,请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: