首页 > 编程笔记 > Java笔记 阅读:1

Java线程池的用法(附带示例)

当系统中存在大量并发线程,且每个线程仅执行短暂任务时,频繁创建和销毁线程会显著降低系统效率。这是因为线程的创建和销毁过程本身消耗时间。

是否存在一种机制,能够使线程被重复利用呢?也就是说,线程在完成一个任务后,不立即销毁,而是继续执行其他任务。解决方案是预先创建一组线程,并将它们存储在所谓的线程池中。

当需要执行任务时,可以直接从线程池中获取线程,任务完成后,线程被归还到线程池中,从而避免了频繁创建和销毁过程,实现了对线程的复用。这与生活中的公共交通工具模式类似。

线程池如下图所示:


图 1 线程池

线程池具有以下优点:

线程池相关API

在 JDK 5.0 之前,我们必须手动自定义线程池。从 JDK 5.0 开始,Java 内置了与线程池相关的 API。java.util.concurrent 包中提供与线程池相关的 API——ExecutorService 和 Executors。

1) ExecutorService

ExecutorService 是真正的线程池接口,常见子类为 ThreadPoolExecutor:

2) Executors

Executors 是一个线程池的工厂类,通过此类的静态工厂方法可以创建多种类型的线程池对象:
【实例 1】创建线程池并利用线程池,代码如下:
public class NumberThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

public class NumberThread02 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

import java.util.concurrent.Callable;

public class NumberThread03 implements Callable {
    @Override
    public Object call() throws Exception {
        int evenSum = 0; // 记录偶数的和
        for (int i = 0; i <= 100; i++) {
            if (i % 2 == 0) {
                evenSum += i;
            }
        }
        return evenSum;
    }
}

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

public class ThreadPoolTest {
    public static void main(String[] args) {
        // 1.提供指定线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        // 设置线程池的属性
        System.out.println(service.getClass()); // ThreadPoolExecutor
        service1.setMaximumPoolSize(50); // 设置线程池中线程数的上限

        // 2.执行指定线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
        service.execute(new NumberThread());    // 适用于Runnable
        service.execute(new NumberThread02());  // 适用于Runnable
        try {
            Future future = service.submit(new NumberThread03()); // 适用于Callable
            System.out.println("总和为:" + future.get());
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 3.关闭连接池
        service.shutdown();
    }
}
在上述代码中,我们构建了一个线程池,并在 NumberThread03 类中通过实现 Callable 接口采用了 JDK 5.0 引入的一种新型线程创建方式。submit() 方法适用于通过 Callable 接口创建的线程。

相关文章