Java 教程

Java 控制语句

面向对象编程

Java 内置类

Java 文件处理

Java 错误与异常

Java 多线程

Java 同步

Java 网络编程

Java 集合

Java 接口

Java 数据结构

Java 集合算法

高级 Java

Java 杂项

Java API与框架

Java 类引用

Java 有用资源

Java - 线程池



线程池

线程池是预初始化线程的集合。线程池背后的总体思路是在方法启动时形成多个线程并将它们放入池中,在那里它们等待工作。当服务器接收到服务请求时,它会从该池中唤醒一个线程(如果可用)并将服务请求传递给它。线程完成服务后,它返回到池中并等待更多工作。如果池中没有可用的线程,则服务器将等待直到一个线程空闲。

为什么在 Java 中使用线程池?

  • 它节省时间,因为无需创建新线程。

  • 它用于ServletJSP,其中容器创建一个线程池来处理请求。

在 Java 中创建线程池

Java 提供的java.util.concurrent.Executors类提供了一些创建线程池的方法。

Executors 类方法

以下是此类中一些重要且有用的方法,用于创建线程池:

序号 方法和描述
1

public static ExecutorService newCachedThreadPool()

创建一个线程池,该线程池根据需要创建新线程,但在可用时将重用先前构造的线程。

2

public static ExecutorService newFixedThreadPool(int nThreads)

创建一个线程池,该线程池重用固定数量的线程,这些线程从共享的无界队列中获取操作。

3

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

创建一个线程池,该线程池可以安排命令在给定延迟后运行,或定期执行。

4

public static ExecutorService newWorkStealingPool()

使用所有可用的处理器作为其目标并行级别来创建一个工作窃取线程池。

使用 newFixedThreadPool() 方法创建线程池

通过调用 Executors 类的静态 newFixedThreadPool() 方法获得固定线程池。

语法

ExecutorService fixedPool = Executors.newFixedThreadPool(2);

其中:

  • 最多 2 个线程将处于活动状态以处理任务。

  • 如果提交超过 2 个线程,则它们将保留在队列中,直到线程可用。

  • 如果线程由于执行期间发生故障而在关闭执行程序之前终止,则会创建一个新线程来代替它。

  • 任何线程都存在,直到池关闭。

示例:使用 newFixedThreadPool() 方法创建线程池

下面的 TestThread 程序显示了使用 Executors newFixedThreadPool() 方法创建两个线程的线程池的用法。我们使用 ThreadPoolExecutor 对象并使用 newFixedThreadPool(2) 初始化,这是一个大小为 2 的固定线程池。然后我们打印线程池的各种属性。然后我们将一些线程添加到执行程序中,然后打印线程池的相同属性以反映更改。

package com.tutorialspoint;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread {
	
   public static void main(final String[] arguments) throws InterruptedException {
      ExecutorService executor = Executors.newFixedThreadPool(2);

      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.submit(new Task());
      executor.submit(new Task());
	  executor.submit(new Task());
      executor.submit(new Task());

      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.shutdown();
   }  

   static class Task implements Runnable {

      public void run() {
         
         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);
            
            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}

输出

Largest executions: 0
Maximum allowed threads: 2
Current threads in pool: 0
Currently executing threads: 0
Total number of threads(ever scheduled): 0
Core threads: 2
Largest executions: 2
Maximum allowed threads: 2
Current threads in pool: 2
Currently executing threads: 2
Total number of threads(ever scheduled): 4
Running Task! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1

这里,虽然我们提交了四个线程,但只执行了两个线程,因为线程池被固定为只接受两个线程。

使用 newCachedThreadPool() 方法创建线程池

通过调用 Executors 类的静态 newCachedThreadPool() 方法获得缓存线程池。

语法

ExecutorService executor = Executors.newCachedThreadPool();

其中:

  • newCachedThreadPool 方法创建一个具有可扩展线程池的执行程序。

  • 此类执行程序适用于启动许多短暂任务的应用程序。

示例:使用 newCachedThreadPool() 方法创建线程池

下面的 TestThread 程序演示了如何使用 Executors 的 newCachedThreadPool() 方法创建一个可扩展的线程池。我们使用 ThreadPoolExecutor 对象并用 newCachedThreadPool() 初始化它。然后我们打印线程池的各种属性。之后我们向执行器添加一些线程,然后再次打印线程池的属性以反映这些变化。

package com.tutorialspoint;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread {
	
   public static void main(final String[] arguments) throws InterruptedException {
      ExecutorService executor = Executors.newCachedThreadPool();

      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.submit(new Task());
      executor.submit(new Task());
	  executor.submit(new Task());
      executor.submit(new Task());

      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.shutdown();
   }  

   static class Task implements Runnable {

      public void run() {
         
         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);
            
            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}

输出

Largest executions: 0
Maximum allowed threads: 2147483647
Current threads in pool: 0
Currently executing threads: 0
Total number of threads(ever scheduled): 0
Core threads: 0
Largest executions: 4
Maximum allowed threads: 2147483647
Current threads in pool: 4
Currently executing threads: 4
Total number of threads(ever scheduled): 4
Running Task! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-4
Running Task! Thread Name: pool-1-thread-3
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-3
Task Completed! Thread Name: pool-1-thread-4
Task Completed! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1

使用 newScheduledThreadPool() 方法创建线程池

通过调用 Executors 类的静态方法 newScheduledThreadPool() 获得一个调度线程池。

语法

ExecutorService executor = Executors.newScheduledThreadPool(1);

示例:使用 newScheduledThreadPool() 方法创建线程池

下面的 TestThread 程序演示了如何使用 Executors 的 newScheduledThreadPool() 方法创建一个线程池。我们使用 ScheduledExecutorService 对象作为调度器,并用 newScheduledThreadPool() 初始化它。我们创建了一个 ScheduledFuture 对象来调度一个任务,该任务在初始延迟两秒后每两秒执行一次。使用调度器,我们将任务计划运行十秒钟。

package com.tutorialspoint;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException {
      final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

      final ScheduledFuture<?> beepHandler = 
         scheduler.scheduleAtFixedRate(new BeepTask(), 2, 2, TimeUnit.SECONDS);

      scheduler.schedule(new Runnable() {

         @Override
         public void run() {
            beepHandler.cancel(true);
            scheduler.shutdown();			
         }
      }, 10, TimeUnit.SECONDS);
   }  

   static class BeepTask implements Runnable {

      public void run() {
         System.out.println("beep");      
      }
   }
}

输出

beep
beep
beep
beep
beep
广告