java四种线程池(基本使用)

标题java四种线程池及使用示例

1、线程工厂

1、我们先来写ThreadFactory,在创建线程池时候可以传入自定义的线程工厂,线程工厂说白了就是用来定制线程的一些属性:名字、优先级、是否为守护线程。直接看代码即可。

当然创建线程池的时候可以不传入自定义线程工厂。

public class MyThreadFactory implements ThreadFactory {
    private static final String thread_prefix = "self_thread";

    private AtomicInteger integer = new AtomicInteger(0);

    private String threadName = null;

    public MyThreadFactory(String threadName) {
        this.threadName = threadName;
    }

    public MyThreadFactory() {
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        String name = threadName == null ? thread_prefix + " " + integer.getAndIncrement() : threadName + " " + integer.getAndIncrement();
        thread.setName(name);

        return thread;
    }
}

2、我们来详细看一下四种线程池

单一线程的线程池可缓存的线程池可周期性执行的线程池固定数目的线程池
.newSingleThreadExecutor.newCachedThreadPool.newScheduledThreadPool.newFixedThreadPool

1、单一线程的线程池:

此线程池只有一个线程,用仅有的一个线程来执行任务,保证所有的任务按照指定顺序(FIFO,LIFO,优先级)执行,所有的任务都保存在队列LinkedBlockingQueue中,等待唯一的单线程来执行任务。

    private static final Object lock = new Object();
    private static int count = 0;
   

private static void testSingleThreadThreadPool() {
        ExecutorService service = Executors.newSingleThreadExecutor(new MyThreadFactory("singleThread"));
        for (int i = 0; i < 6; i++) {
            test(service);
        }
    }


    private static void test(ExecutorService service) {
        synchronized (lock) {
            count++;
            System.out.println(Thread.currentThread().getName());

            if (count == 5) {
                System.out.println("count == 5 shutdown ");
                service.shutdown();
            }
        }
    }

可以从输出看到,只new了一个线程。

2、可缓存的线程池

创建一个可缓存的无界线程池,如果线程池长度超过处理需要,可灵活回收空线程,若无可回收,则新建线程。当线程池中的线程空闲时间超过60s,则会自动回收该线程,当任务超过线程池的线程数则创建新的线程,线程池的大小上限为Integer.MAX_VALUE,可看作无限大。

   private static void testCachedThreadPool() {
        ExecutorService service = Executors.newCachedThreadPool(new MyThreadFactory("cached"));
        for (int i = 0; i < 1000; i++) { // 循环数稍微大一点 模拟线程回收后被复用
            service.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()); // 可从控制台看出相同线程名的线程
                }
            });
        }
    }

3、可周期性执行的线程池

    private static void testScheduleThreadPool() {
        /**
         * 可周期性执行的线程池 延迟2秒执行 每间隔4秒执行一次
         *
         * 是“以固定的频率”执行,period(周期)指的是两次成功执行之间的时间。
         * 上一个任务开始的时间计时,一个period后,检测上一个任务是否执行完毕,
         * 如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,
         * 则需要等上一个任务执行完毕后立即执行。
         */
        ExecutorService service = Executors.newScheduledThreadPool(6, new MyThreadFactory());
        ((ScheduledExecutorService) service).scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                test(service);
            }
        }, 2, 4, TimeUnit.SECONDS);

        // 定时  执行一次   的任务,延迟1s后执行
        ((ScheduledExecutorService) service).schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + ", delay 1s");

            }
        }, 1, TimeUnit.SECONDS);


        /**
         * “以固定的延时”执行,delay(延时)指的是一次执行终止和下一次执行开始之间的延迟。
         */
        ((ScheduledExecutorService) service).scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                long start = new Date().getTime();
                System.out.println("scheduleWithFixedDelay 开始执行时间:" +
                        DateFormat.getTimeInstance().format(new Date()));
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                long end = new Date().getTime();
                System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 + "m");
                System.out.println("scheduleWithFixedDelay执行完成时间:"
                        + DateFormat.getTimeInstance().format(new Date()));
                System.out.println();
                System.out.println();
            }
        }, 2, 3, TimeUnit.SECONDS);

    }

4、固定数目的线程池

这个就很好理解了。固定数量的线程。

    /**
     * 固定数量的线程池
     */
    private static void testFixedThreadPool() {
        ExecutorService service = Executors.newFixedThreadPool(5, new MyThreadFactory());
        for (int i = 0; i < 8; i++) {
            service.submit(new Runnable() {
                @Override
                public void run() {
                    test(service);
                }
            });
        }
    }

5、方法对比

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java中,你可以使用线程池来管理和复用线程,以提高线程的执行效率和资源利用率。Java提供了`java.util.concurrent`包中的`ExecutorService`接口和`ThreadPoolExecutor`类来实现线程池。 以下是使用线程池基本步骤: 1. 创建线程池对象:你可以使用`Executors`类提供的工厂方法来创建线程池。例如,可以使用`Executors.newFixedThreadPool(int nThreads)`方法创建一个固定大小的线程池,其中`nThreads`参数指定线程池的最大线程数。 ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个包含5个线程的线程池 ``` 2. 提交任务给线程池:你可以使用`execute(Runnable task)`方法将任务提交给线程池执行。任务是实现了`Runnable`接口的对象。 ```java executor.execute(new MyTask()); // 提交一个任务给线程池执行 ``` 3. 关闭线程池:在不需要继续提交任务给线程池时,你应该显式地关闭线程池,释放资源。可以调用`shutdown()`方法来平缓地关闭线程池,等待所有已提交的任务完成执行。也可以调用`shutdownNow()`方法来立即关闭线程池,并尝试中断正在执行的任务。 ```java executor.shutdown(); // 平缓地关闭线程池 ``` 完整示例代码如下: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { executor.execute(new MyTask(i)); } executor.shutdown(); } static class MyTask implements Runnable { private int taskId; public MyTask(int taskId) { this.taskId = taskId; } public void run() { System.out.println("Task " + taskId + " is running."); // 执行任务的逻辑 } } } ``` 在上面的示例中,我们创建了一个固定大小为5的线程池,并提交了10个任务给线程池执行。每个任务都是`MyTask`类的实例,实现了`Runnable`接口的`run()`方法,该方法定义了任务的逻辑。 希望这能帮助到你!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

约翰兰博之西安分博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值