加载中...

线程池详解

线程池的种类:

1. JDK线程池----是java自带的API,比较偏底层,很少用,有必要了解

------(1)jdk普通线程池:ExecutorService

------(2)jdk定时任务线程池:ScheduledExecutorService

2. Spring线程池----做了封装

------(1)Spring普通线程池:ThreadPoolTaskExecutor

------(2)Spring定时任务线程池:ThreadPoolTaskScheduler

------(3)Spring普通线程池(简化版)

------(4)Spring定时任务线程池(简化版)

3.分布式定时任务线程池----Spring QuartZ

下面逐个用实列演示:

1.jdk普通线程池:ExecutorService------在Test中测试,代码如下:

 1 @SpringBootTest
 2 public class ThreadPoolTests {
 3 
 4     private static final Logger logger =LoggerFactory.getLogger(ThreadPoolTests.class);
 5 
 8     private ExecutorService executorService = Executors.newFixedThreadPool(5);//通过Executors这个工厂或者工具类创建线程,线程数量位5,哪个线程空闲就会执行任务
 9 
10   //Test中的线程执行完了就会结束,不会等一下看还有没有任务,因此需要定义一个sleep方法让这些线程等一下
11     private void sleep(long m) {//sleep方法经常抛异常,封装一下,处理一下异常
12         try {
13             Thread.sleep(m);
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17     }
18 
19     // 1.JDK普通线程池
20     @Test
21     public void testExecutorService() {
22         Runnable task = new Runnable() {//实现Runnable接口,这里是匿名实现,方法中写要执行的方法
23             @Override
24             public void run() {
26                  logger.warn("Hello ExecutorService");
27             }
28         };
29 
30         for (int i = 0; i < 10; i++) {
31             executorService.submit(task);//提交任务给线程池,就会安排线程处理
32         }
        
sleep(10000);//加上这个之后,打印结果之后程序还会运行秒,这是为了防止有的线程还没有打印完线程就结束了
33 35 }


插入:理解Thread.Sleep(10000)的含义,可以参考这篇文章https://blog.csdn.net/agony_sun/article/details/78031520

    解释:Unix系统使用的是时间片算法,而Windows则属于抢占式的。抢占式表示,等一个进程用完CPU后,谁的优先级高,就给谁,而不是排队。一般情况下,一个进程除非自己主动放弃CPU 的试用权,不然不可以被剥夺。Thread.Sleep(10000)表示未来10000毫秒内(10秒内)该线程都不需要CPU资源,也就是说,这期间的CPU竞争都不会把该进程算在内(CPU竞争就是将这些线程的优先级排个序,看把CPU给谁用)。等到10钟到了的时候,该进程又会参与竞争。那么在这里,sleep(10000)的作用就是让testExecutorService()方法一直运行着,等到第10秒的时候,操作系统又会来这个方法中看,话有哪些进程参与竞争。但是

行结果如下:打印任务几乎同时完成,但是随机由不同的线程完成

 2.JDK定时任务线程池

@SpringBootTest
public class ThreadPoolTests {

    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolTests.class);

    // JDK可执行定时任务的线程池
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

     //Test中的线程执行完了就会结束,不会等一下看还有没有任务,因此需要定义一个sleep方法让这些线程等一下
    private void sleep(long m) {//sleep方法经常抛异常,封装一下,处理一下异常
        try {
            Thread.sleep(m);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    // 2.JDK定时任务线程池
    @Test
    public void testScheduledExecutorService() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.warn("Hello ScheduledExecutorService");
            }
        };
 //initialDelay:5000是点击执行之后到程序正式执行的延迟时间;period:1000是时间间隔;TimeUnit:时间单位 
scheduledExecutorService.scheduleAtFixedRate(task, 5000,1000, TimeUnit.MILLISECONDS); 
sleep(
20000); //方法一开始运行就会生效,该方法总共会运行20秒;这里只是测试,需要这样让该方法一直运行,真实运行的项目不需要这样设置
}
执行结果如下图:不同的线程,每秒完成一次打印任务----总共执行了20秒,与设定的时间刚好—致,initialDelay了5秒,打印了15秒

 

 

 

 


3.Spring普通线程池
实现步骤:
步骤1:在application.properties配置线程数量等信息
1 # TaskExecutionProperties----Spring普通线程池
2 spring.task.execution.pool.core-size=5
3 spring.task.execution.pool.max-size=15
4 spring.task.execution.pool.queue-capacity=100

步骤2:写ThreadPoolConfig配置类

@Configuration
@EnableScheduling//声明启用Scheduling,不然不会启用,会报错
@EnableAsync
public class ThreadPoolConfig {
}

步骤3:写测试代码

 1 @SpringBootTest
 2 public class ThreadPoolTests {
 3 
 4     private static final Logger logger = LoggerFactory.getLogger(ThreadPoolTests.class);
 5 
 6     // JDK可执行定时任务的线程池
 7     private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
 8 
 9      //Test中的线程执行完了就会结束,不会等一下看还有没有任务,因此需要定义一个sleep方法让这些线程等一下
10     private void sleep(long m) {//sleep方法经常抛异常,封装一下,处理一下异常
11         try {
12             Thread.sleep(m);
13         } catch (InterruptedException e) {
14             e.printStackTrace();
15         }
16     }
17      // 3.Spring普通线程池
18     @Test
19     public void testThreadPoolTaskExecutor() {
20         Runnable task = new Runnable() {
21             @Override
22             public void run() {
23 
24                 logger.warn("Hello ThreadPoolTaskExecutor");
25             }
26         };
27 
28         for (int i = 0; i < 10; i++) {
29             taskExecutor.submit(task);
30         }
31 
32         sleep(10000);//加上这个之后,打印结果之后程序还会运行10秒,这是为了防止有的线程还没有打印完线程就结束了
33 }

运行结果:打印任务几乎同时完成,但是随机由不同的线程完成

 

 

 4.Spring定时任务线程池
实现步骤:
步骤1:在application.properties配置线程数量等信息
1 # TaskSchedulingProperties-----Spring可执行定时任务的线程池
2 spring.task.scheduling.pool.size=5

步骤2:写ThreadPoolConfig配置类

 

1 @Configuration
2 @EnableScheduling//声明启用Scheduling,不然不会启用,会报错
3 @EnableAsync
4 public class ThreadPoolConfig {
5 }

步骤3:写测试代码

@SpringBootTest
public class ThreadPoolTests {

    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolTests.class);

    // JDK可执行定时任务的线程池
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

     //Test中的线程执行完了就会结束,不会等一下看还有没有任务,因此需要定义一个sleep方法让这些线程等一下
    private void sleep(long m) {//sleep方法经常抛异常,封装一下,处理一下异常
        try {
            Thread.sleep(m);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    // 4.Spring定时任务线程池
    @Test
    public void testThreadPoolTaskScheduler() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.debug("Hello ThreadPoolTaskScheduler");
            }
        };

        Date startTime = new Date(System.currentTimeMillis() + 2000);
        taskScheduler.scheduleAtFixedRate(task, startTime, 1000);

        sleep(25000);
    }
执行结果如下图:不同的线程,每秒完成一次打印任务---总共执行了23秒,与设定的时间刚好—致,sleep()了25秒,System.currentTimeMillis() + 2000推迟了2秒

 

5.Spring普通线程池(简化)---配置比较多,但是任务较多时,比可以通过配置简化操作
步骤1:
在AlphaService中写execute1,execute2方法,并加上注解 @Async
@Service
public class AlphaService {
 private static final Logger logger = LoggerFactory.getLogger(AlphaService.class);

    @Async
    public void execute1() {
        logger.warn("execute1");
    }
}

 步骤2:在application.properties配置线程数量等信息

1 # TaskExecutionProperties----Spring普通线程池
2 spring.task.execution.pool.core-size=5
3 spring.task.execution.pool.max-size=15
4 spring.task.execution.pool.queue-capacity=100

步骤3:写ThreadPoolConfig配置类

 
1 @Configuration
2 @EnableScheduling//声明启用Scheduling,不然不会启用,会报错
3 @EnableAsync
4 public class ThreadPoolConfig {
5 }

步骤4:写测试代码

 1 @SpringBootTest
 2 public class ThreadPoolTests {
 3 
 4     private static final Logger logger = LoggerFactory.getLogger(ThreadPoolTests.class);
 5 
 6  //Test中的线程执行完了就会结束,不会等一下看还有没有任务,因此需要定义一个sleep方法让这些线程等一下
 7     private void sleep(long m) {//sleep方法经常抛异常,封装一下,处理一下异常
 8         try {
 9             Thread.sleep(m);
10         } catch (InterruptedException e) {
11             e.printStackTrace();
12         }
13     }
14 
15  // 5.Spring普通线程池(简化)
16     @Test
17     public void testThreadPoolTaskExecutorSimple() {
18         for (int i = 0; i < 10; i++) {
19             alphaService.execute1();
20         }
21 
22         sleep(10000);
23     }
24 }

运行结果:

 

 

 

6.Spring可执行定时任务的线程池(简化)

步骤1:在AlphaService中写execute2方法,并加上注解@Scheduled
 1 @Service
 2 public class AlphaService {
 3 
 4     private static final Logger logger = LoggerFactory.getLogger(AlphaService.class);
 5 
 6     @Scheduled(initialDelay = 5000, fixedRate = 1000)
 7     public void execute2() {
 8         logger.warn("execute2");
 9     }
10 }

 

 步骤2:在application.properties配置线程数量等信息
1 # TaskSchedulingProperties-----Spring可执行定时任务的线程池
2 spring.task.scheduling.pool.size=5

 

步骤3:写ThreadPoolConfig配置类
@Configuration
@EnableScheduling//声明启用Scheduling,不然不会启用,会报错
@EnableAsync
public class ThreadPoolConfig {
}

步骤4:写测试代码

 @SpringBootTest
 public class ThreadPoolTests {
 
     private static final Logger logger = LoggerFactory.getLogger(ThreadPoolTests.class);
  
  //Test中的线程执行完了就会结束,不会等一下看还有没有任务,因此需要定义一个sleep方法让这些线程等一下
      private void sleep(long m) {//sleep方法经常抛异常,封装一下,处理一下异常
          try {
              Thread.sleep(m);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }

    // 6.Spring定时任务线程池(简化)
    @Test
    public void testThreadPoolTaskSchedulerSimple() {
        sleep(15000);
    }
 }

 

 QuartZ请看https://i.cnblogs.com/posts/edit-done;postId=15914357



posted @ 2022-02-18 12:28  甜甜筒  阅读(159)  评论(0编辑  收藏  举报