线程池的使用

转载文章:Tom_殇子

线程池

1.为什么使用线程池:

a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。

2.线程池使用方法:通过Executors创建四种线程池

1.newCachedThreadPool: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程池的规模不存在限制。ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
2.newFixedThreadPool: 创建一个固定长度线程池,可控制线程最大并发数,超出的线程会在队列中等待。ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int型线程池长度参数);
3.newScheduledThreadPool: 创建一个固定长度线程池,支持定时及周期性任务执行。ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(int型线程池长度参数);
4.newSingleThreadExecutor: 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

3.线程怎么加入线程池:线程加入后相当于准备运行状态

1.cachedThreadPool、fixedThreadPool、singleThreadExecutor: submit(Runnable task) submit(Callable task)、submit(Runnable)
2.scheduledExecutorService: scheduleWithFixedDelay(Runnable a,intidelay:int型时间,delay:int型时间, TimeUnit.SECONDS)、scheduleAtFixedRate(Runnable a,delay:int型时间, TimeUnit.SECONDS)、schedule(Runnable a,delay:int型时间, TimeUnit.SECONDS)第一个方法表示整个定时间隔任务先延迟initdelay时间,后开始执行定时任务,再间隔delay时间执行定时任务,依次循环。后两个方法一样,相较于第一个方法区别是没有整个定时任务的初始延迟。

代码示例:


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

public class NewThreadPool {
    public static void main(String[] args) {
        //创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程池的规模不存在限制。
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            //1- 在未来某个时间执行给定的命令。
            // 该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
            cachedThreadPool.execute(() -> {//lambda表达式
                {
                    System.out.println(index + ":" + Thread.currentThread().getName());
                }
            });

            //2- 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
            // 该 Future 的 get 方法在成功完成时将会返回给定的结果
            cachedThreadPool.submit(() -> {
                {
                    System.out.println(index + ":" + Thread.currentThread().getName());
                }
            });
        }
        cachedThreadPool.shutdown();//关闭线程池
        System.out.println("newCacheThreadool结束");
        //创建一个固定长度线程池,可控制线程最大并发数,超出的线程会在队列中等待。
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 10; i++) {
            final int index = i;

            //1- 在未来某个时间执行给定的命令。
            // 该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
            fixedThreadPool.execute(() -> {
                {
                    threadRunMethod(index);
                }
            });

            //2- 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
            // 该 Future 的 get 方法在成功完成时将会返回给定的结果
            fixedThreadPool.submit(() -> {
                {
                    threadRunMethod(index);
                }
            });
        }
        fixedThreadPool.shutdown();
        System.out.println("newFixedThreadPool结束");

        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

        //testSchedule(scheduledExecutorService);

        //testScheduleAtFixedRate(scheduledExecutorService);

        testScheduleWithFixedDelay(scheduledExecutorService);

        // 终止线程池
        scheduledExecutorService.shutdown();
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            /*singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("newSingleThreadExecutor: " + index);
                        Thread.sleep(2*1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });*/


            singleThreadExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("newSingleThreadExecutor: " + index);
                        Thread.sleep(2*1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        singleThreadExecutor.shutdown();
    }



    /**
     *
     * 跟 testScheduleAtFixedRate 非常类似,就是延迟的时间有点区别
     * 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
     * 也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,
     * 接着在 initialDelay + 2 * period 后执行,依此类推。
     *
     * 如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
     * 推迟的时间 : 等到上次的任务执行完之后再延迟period 的时间后执行。
     * @param scheduledExecutorService
     */
    private static void testScheduleWithFixedDelay(ScheduledExecutorService scheduledExecutorService) {
        scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("延迟2秒,再3秒执行一次"+Thread.currentThread().getName());
                    //如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
                    //本次任务执行完后下次的任务还需要延迟period时间后再执行
                    Thread.sleep(6*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },2,3, TimeUnit.SECONDS);
    }

    /**
     * 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
     * 也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,
     * 接着在 initialDelay + 2 * period 后执行,依此类推。
     *
     * 如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
     * 推迟的时间 : 等到上次的任务执行完就立马执行。
     * @param scheduledExecutorService
     */
    private static void testScheduleAtFixedRate(ScheduledExecutorService scheduledExecutorService) {
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("延迟2秒,再3秒执行一次"+Thread.currentThread().getName());
                    //如果任务里面执行的时间大于 period 的时间,下一次的任务会推迟执行。
                    //如果任务里面执行的时间大于 period 的时间,本次任务执行完后,下次任务立马执行。
                    Thread.sleep(6*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        },2,3,TimeUnit.SECONDS);
    }

    /**
     * 创建并执行在给定延迟后启用的一次性操作
     * @param scheduledExecutorService
     */
    private static void testSchedule(ScheduledExecutorService scheduledExecutorService) {
        scheduledExecutorService.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("delay 3 seconds"+Thread.currentThread().getName());
            }
        }, 3, TimeUnit.SECONDS);
    }

    private static void threadRunMethod(int index) {
        try {
            System.out.println(index+":"+Thread.currentThread().getName());
            Thread.sleep(1000);//因为创建线程是串行的,其他线程需要等待现有线程结束才开始创建运行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值