Administrator
发布于 2023-06-18 / 77 阅读 / 0 评论 / 0 点赞

在Java中,常用的线程池,及使用方式

在Java中,常用的线程池实现有以下几种:

  1. FixedThreadPool(固定线程池):

    • 特点:线程数固定,适用于长期执行的任务,控制并发线程数。
    • 优点:线程数固定,不会因为任务数量增多而创建过多的线程,可以控制线程的最大数量,避免资源耗尽。
    • 缺点:当线程数达到最大值时,新的任务需要等待空闲线程,可能会导致一些任务等待的时间较长。
  2. CachedThreadPool(缓存线程池):

    • 特点:线程数根据任务的数量动态调整,适用于短期异步任务。
    • 优点:线程数根据任务的数量自动调整,可以灵活地处理大量的短期任务,避免线程空闲浪费资源。
    • 缺点:线程数的动态调整可能会导致创建和销毁线程的开销较大,如果任务量过大,可能会导致创建过多的线程。
  3. SingleThreadExecutor(单线程线程池):

    • 特点:只有一个工作线程,适用于需要顺序执行的任务。
    • 优点:保证任务的顺序执行,避免多线程情况下的并发问题。
    • 缺点:只有一个线程执行任务,无法并行处理多个任务。
  4. ScheduledThreadPool(定时线程池):

    • 特点:可以按照指定的时间间隔执行任务。

    • 优点:可以按照固定的时间间隔执行任务,适用于需要定时执行的任务。

    • 缺点:线程数固定,当任务量过大时,可能会导致任务等待的时间较长。

这些线程池实现都是通过java.util.concurrent.ExecutorService接口来提供线程池的功能。根据实际需求选择合适的线程池实现,可以根据任务类型、任务量、并发性要求等因素进行选择,以达到最优的性能和资源利用。

以下是线程池的用法和一些常见的用例:

  1. 创建线程池:
ExecutorService executor = Executors.newFixedThreadPool(5);

提交任务给线程池执行:

executor.submit(new Runnable() {
    public void run() {
        // 执行任务逻辑
    }
});

关闭线程池:

executor.shutdown();

控制并发线程数:

ExecutorService executor = Executors.newFixedThreadPool(5);
// 控制并发线程数为3
Semaphore semaphore = new Semaphore(3);

for (int i = 0; i < 10; i++) {
    executor.submit(new Runnable() {
        public void run() {
            try {
                // 获取许可证
                semaphore.acquire();
                // 执行任务逻辑
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放许可证
                semaphore.release();
            }
        }
    });
}

定时执行任务:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
// 延迟2秒后执行任务
executor.schedule(new Runnable() {
    public void run() {
        // 执行任务逻辑
    }
}, 2, TimeUnit.SECONDS);

处理任务的返回结果:

ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<>();

for (int i = 0; i < 10; i++) {
    Future<String> future = executor.submit(new Callable<String>() {
        public String call() throws Exception {
            // 执行任务逻辑
            return "Task result";
        }
    });
    futures.add(future);
}

for (Future<String> future : futures) {
    try {
        String result = future.get();
        // 处理任务返回结果
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

这些是线程池的基本用法和一些常见的使用示例。根据具体需求,可以使用不同的线程池实现和调整线程池的参数,以满足任务的处理需求和性能要求。

具体可执行代码示例:

package com.zhumeng;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

import static java.lang.Thread.sleep;

public class Main {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        // 控制并发线程数为3
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 100; i++) {
            executor.submit(new Runnable() {
                public void run() {
                    try {
                        // 获取许可证
                        semaphore.acquire();
                        // 执行任务逻辑
                        long threadId = Thread.currentThread().getId();  // 取当前线程id
                        Random random = new Random();
                        int i1 = random.nextInt(1000); //随机毫秒数
                        // 睡眠帮助显现效果
                        sleep(i1);
                        System.out.println("Current Thread ID: " + threadId + ";time:"+System.currentTimeMillis() + " ;sleep:" + i1);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        // 释放许可证
                        semaphore.release();
                    }
                }
            });
        }
    }
}

可以帮助认识和熟悉多线程程序的使用。


评论