一起Talk Android吧(第三百七十一回:多线程之线程池扩展)

本文详细介绍了Android中线程池的使用步骤,包括创建线程池、提交任务和关闭线程池。通过示例程序展示了线程池在不同场景下的行为,如核心线程处理任务、任务队列的利用以及超出最大线程数时的异常处理。强调了自定义线程池的重要性,并总结了线程池使用的关键点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

各位看官们,大家好,上一回中咱们说的是Android中多线程之线程池回顾的例子,这一回中咱们介绍的例子是多线程之线程池扩展。闲话休提,言归正转。让我们一起Talk Android吧!

使用步骤

看官们,我们在上一章回中回顾了线程池相关的内容,并且重点介绍了ThreadPoolExecutor类的构造方法,本章回中将通过具体的示例代码来介绍如何使用此方法来创建线程池。不过线程池的使用步骤不变,还是三步曲:

  • 1.创建线程池
  • 2.创建线程并且加入到线程池中(execute()/submit());
  • 3.关闭线程池(程序异常时关闭)

示例程序

下面是示例程序,请大家参考

public class ThreadPool {
    //ExecutorService接口代表线程池,通过使用它的实现类ThreadPoolExecutor,创建此类的对象相当于创建线程池
    public static void main(String[] args) throws Exception{
        int mCorePoolSize = 2;
        int mMaxPoolSize = 3;
        int mPoolKeepAliveTime = 2;

        ExecutorService executorService = new ThreadPoolExecutor(mCorePoolSize,mMaxPoolSize,mPoolKeepAliveTime, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

        Thread thread1 = new Thread(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" is running...");
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Thread thread2 = new Thread(()->{ System.out.println(Thread.currentThread().getName()+" is running...");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread thread3 = new Thread(()->{ System.out.println(Thread.currentThread().getName()+" is running...");});
        Thread thread4 = new Thread(()->{ System.out.println(Thread.currentThread().getName()+" is running...");});
        Thread thread5 = new Thread(()->{ System.out.println(Thread.currentThread().getName()+" is running...");});

        /*
        executorService.execute(thread1);
        executorService.execute(thread2);
        executorService.execute(thread3);
        executorService.execute(thread4);
        executorService.execute(thread5);

         */
        /* ************* step 1 ************** */
        //使用两个core线程处理任务
        executorService.submit(thread1);
        executorService.submit(thread2);

        /* ************* step 2 ************** */
        //使用长度为2的任务队列存放任务,core线程处理完任务后从任务队列中拿出任务继续处理
        executorService.submit(thread1);
        executorService.submit(thread2);

        /* ************* step 3 ************** */
        //core线程正在处理任务,而且任务队列也满了会创建一个临时线程来处理任务
        executorService.submit(thread3);

        /* ************* step 4 ************** */
        //core线程正在处理任务,而且任务队列也满了会创建一个临时线程来处理任务,
        //创建了临时任务也在忙,再创建一个临时任务,但是超过线程池最大线程数3,引发异常
        executorService.submit(thread4);

        executorService.shutdown();
    }
}

程序演示

我们在上面的代码中创建了一个自定义的线程池,其中包含2个核心线程、3个最大线程,任务队列的长度为2.大家先把step1-4这部分代码注释掉,然后依次释放step1-4注释中的程序,可以得到以下运行结果

演示1
//第一步:线程中只有两个线程在运行
pool-1-thread-2 is running...
pool-1-thread-1 is running...
演示2
//第二步:线程中只有两个线程在运行,任务队列中有两个任务,完成当作任务后再从任务队列中获取新任务
pool-1-thread-2 is running...
pool-1-thread-1 is running...
pool-1-thread-2 is running...
pool-1-thread-1 is running...
演示3
//第三步:线程中有两个线程在运行,任务队列中有两个任务,再来一个任务时创建了临时线程(Thread-3)来完成任务
pool-1-thread-2 is running...
pool-1-thread-3 is running...
pool-1-thread-1 is running...
pool-1-thread-3 is running...
pool-1-thread-2 is running...
演示4
//第四步线程中有两个线程在运行,任务队列中有两个任务,再来一个任务时创建了临时线程(Thread-3)来完成任务
//再来另外一个任务时需要创建临时线程(Thread-4)来完成任务,但是超过了线程池中最大线程数量(3),因此发生异常
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1b2c6ec2[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@30dae81[Wrapped task = Thread[Thread-3,5,main]]] rejected from java.util.concurrent.ThreadPoolExecutor@4edde6e5[Running, pool size = 3, active threads = 3, queued tasks = 2, completed tasks = 0]
  at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2057)
  at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:827)
  at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
  at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
  at com.thread.ex.ThreadPool.main(ThreadPool.java:75)
pool-1-thread-2 is running...
pool-1-thread-1 is running...
pool-1-thread-3 is running...
pool-1-thread-3 is running...
pool-1-thread-2 is running...

这个示例中包含了多个操作,希望大家自己动手去实践一下,这样才能体会到自定义线程池背后的运行逻辑。

内容总结

当然了,如果项目中的线程数量不是特别多也可以使用静态方法来创建线程池,毕竟这种方法使用方便一些。如果项目中线程数量特别多,最好还是以自定义的方式创建线程池。比如阿里的编码规范中就明确要求不能使用静态方法来创建线程池。

最后我们对线程池的知识做统一的总结:

  • 1.线程池的使用方法掌握三步曲就可以;
  • 2.创建线程池时依据项目中线程的数量来决定使用静态方法还是自定义方法创建线程池;
  • 3.添加线程到线程池中时使用submit()方法多一些,毕竟它可以添加多种线程到线程池中;
  • 4.线程池通常不需要关闭,如果遇到异常了最好关闭线程池;

看官们,关于Android中多线程之线程池扩展的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talk_8

真诚赞赏,手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值