java多线程 线程池的使用

野性酷女 2022-10-06 05:56 356阅读 0赞

java线程池

        • 说明
        • 实例
        • 总结

说明

目前大家有在使用的,例如数据库连接池等其他的池技术,可以有效使用资源,方便控制,线程池也是如此,目前线程的使用都是从线程池,很少自己单独创建,维护线程的使用。

在这里插入图片描述

实例

  1. package com.example.demo.pool;
  2. import java.util.Date;
  3. import java.util.concurrent.ArrayBlockingQueue;
  4. import java.util.concurrent.Callable;
  5. import java.util.concurrent.ExecutionException;
  6. import java.util.concurrent.Future;
  7. import java.util.concurrent.ThreadPoolExecutor;
  8. import java.util.concurrent.TimeUnit;
  9. public class PoolTest {
  10. public static void main(String[] args) throws InterruptedException, ExecutionException {
  11. ThreadPoolExecutor pool = new ThreadPoolExecutor(10,20,6,TimeUnit.SECONDS,new ArrayBlockingQueue(20),new ThreadPoolExecutor.CallerRunsPolicy());
  12. for(int i = 0 ;i<3;i++) {
  13. Runnable work = new MyThreadTest();
  14. pool.execute(work);
  15. }
  16. for(int i = 0 ;i<3;i++) {
  17. Callable work1 = new MyThreadCallTest();
  18. Future future = pool.submit(work1);
  19. System.out.println("接收到的参数:"+ String.valueOf(future.get()));
  20. }
  21. }
  22. }
  23. class MyThreadTest implements Runnable {
  24. @Override
  25. public void run() {
  26. // TODO Auto-generated method stub
  27. //synchronized (MyThreadTest.class) {
  28. System.out.println("当前的Call流程:"+Thread.currentThread().getName()+"开始"+new Date());
  29. try {
  30. Thread.sleep(3000);
  31. } catch (InterruptedException e) {
  32. // TODO Auto-generated catch block
  33. e.printStackTrace();
  34. }
  35. System.out.println("当前的Call流程:"+Thread.currentThread().getName()+"结束"+new Date());
  36. //}
  37. }
  38. }
  39. class MyThreadCallTest implements Callable<String>{
  40. @Override
  41. public String call() throws Exception {
  42. // TODO Auto-generated method stub
  43. //synchronized (MyThreadCallTest.class) {
  44. System.out.println("当前的流程:"+Thread.currentThread().getName()+"开始"+new Date());
  45. try {
  46. Thread.sleep(3000);
  47. } catch (InterruptedException e) {
  48. // TODO Auto-generated catch block
  49. e.printStackTrace();
  50. }
  51. System.out.println("当前的流程:"+Thread.currentThread().getName()+"结束"+new Date());
  52. // }
  53. return Thread.currentThread().getName()+"返回结果";
  54. }
  55. }

总结

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的资源浪费。
  2. 提高响应速度。当任务到达时,不需要等到线程创建就能立即执行。
  3. 方便管理线程。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以对线程进行统一的分配,优化及监控。
  1. 参数 corePoolSize

    表示线程池的常驻核心线程数。如果设置为 0,则表示在没有任何任务时,销毁线程池;如果大于 0,即使没有任务时也会保证线程池的线程数量等于此值;
    应该结合实际业务设置此值的大小。若 corePoolSize 的值较小,则会出现频繁创建和销毁线程情况;若值较大,则会浪费系统资源。

  2. 参数 maximumPoolSize

    表示线程池最大可以创建的线程数。官方规定此值必须大于 0,也必须大于等于 corePoolSize 的值;
    此值只有在任务比较多,且不能存放在任务队列时,才会用到。

  3. 参数 keepAliveTime

    表示线程的存活时间。当线程池空闲时并且超过了此时间,多余的线程就会销毁,直到线程池中的线程数等于 corePoolSize 的值为止;
    若 maximumPoolSize 的值 等于 corePoolSize 的值,则线程池在空闲的时候不会销毁任何线程。

  4. 参数 unit

    表示存活时间的单位,配合 keepAliveTime 参数共同使用。

  5. 参数 workQueue

    表示线程池执行的任务队列;
    当线程池的所有线程都在处理任务时,若来了新任务则会缓存到此任务队列中,然后等待执行。

  6. 参数 threadFactory

    表示线程的创建工厂,一般使用默认的线程创建工厂的方法 Executors.defaultThreadFactory()来创建线程。

  7. 参数 RejectedExecutionHandler

    表示指定线程池的拒绝策略,属于一种限流保护的机制;
    当线程池的任务已经在缓存队列 workQueue 中存满了之后,并且不能创建新的线程来执行此任务时,就会用到此拒绝策略
    四种拒绝策略
    (1) AbortPolicy: 丢弃任务并抛出异常。
    (2) DiscardPolicy:丢弃任务但不抛出异常。
    (3) DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务
    (4) CallerRunsPolicy:由调用线程处理该任务

    submit() 方法可以配合 Future来接收线程执行的返回值,而 execute() 不能接收返回值;
    execute() 方法属于 Executor 接口的方法,而 submit() 方法则是属于 ExecutorService 接口的方法。

发表评论

表情:
评论列表 (有 0 条评论,356人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线15/使用线

    使用线程池 背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可

    相关 java线-线

    线程池-基本原理 概述 : ​ 提到池,大家应该能想到的就是水池。水池就是一个容器,在该容器中存储了很多的水。那么什么是线程池呢?线程池也是可以看做成一个池子,在该池子