Java并发

Java并发系列:线程池ThreadPoolExecutor基本

2020-09-01  本文已影响0人  h2coder

上一篇说到,线程的创建和销毁耗费的资源是很多的,我们应该使用线程池来代替显式创建线程,复用线程执行我们的任务,本篇我们就来学习一下线程池的基本使用吧~

线程池的创建

既然要使用线程池,那么首先就需要创建线程池了。在JDK1.5以上版本,Java提供了Executors类,它其实可以说是一个工厂类,创建线程池需要比较多的一些参数,而Executors则提供了一批更加语义化的创建线程池的静态方法。

//创建一个线程池,容量大小为Integer.MAX_VALUE,所以是无限大
ExecutorService pool = Executors.newCachedThreadPool();

//创建容量为1的线程池,它的执行是串行的
ExecutorService pool = Executors.newSingleThreadExecutor();

//创建固定容量大小的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);

//周期性任务线程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);

提交任务到线程池

创建完线程池,接下来就是提交任务到线程池中执行了~执行方法常用有2种,execute()和submit()。

示例

/**
 * 提交Runnable任务
 */
private static void executeByRunnable() {
    ExecutorService pool = Executors.newCachedThreadPool();
    pool.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println("我在execute()中执行任务");
        }
    });
}

//输出
我在execute()中执行任务
/**
 * 提交Callable任务
 */
private static void submitByCallable() {
    try {
        ExecutorService pool = Executors.newCachedThreadPool();
        Future<String> future = pool.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果";
            }
        });
        String result = future.get();
        System.out.println("result: " + result);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

//输出
result: 我是结果
/**
 * 随机执行任务集合中的任意一个任务
 */
private static void runRandomTask() {
    try {
        ExecutorService pool = Executors.newCachedThreadPool();
        ArrayList<Callable<String>> taskList = new ArrayList<>();
        taskList.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果1";
            }
        });
        taskList.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果2";
            }
        });
        taskList.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果3";
            }
        });
        String result = pool.invokeAny(taskList);
        System.out.println("运行结果:" + result);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

//输出
运行结果:我是结果1
/**
 * 执行所有任务
 */
private static void runAllTask() {
    try {
        ExecutorService pool = Executors.newCachedThreadPool();
        ArrayList<Callable<String>> taskList = new ArrayList<>();
        taskList.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果1";
            }
        });
        taskList.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果2";
            }
        });
        taskList.add(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "我是结果3";
            }
        });
        List<Future<String>> futures = pool.invokeAll(taskList);
        for (Future<String> future : futures) {
            String result = future.get();
            System.out.println("获取结果:" + result);
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

//输出
获取结果:我是结果1
获取结果:我是结果2
获取结果:我是结果3

关闭线程池

如果我们需要关闭线程池,有2种方法,shutdown()和shutdownNow()。

/**
 * 关闭线程池,会等待任务执行完毕后再关闭
 */
private static void shutdownThreadPool() {
    ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);
    pool.schedule(new Runnable() {
        @Override
        public void run() {
            System.out.println("我是执行结果...");
        }
    }, 1, TimeUnit.SECONDS);
    pool.shutdown();
}

//输出
我是执行结果...
/**
 * 马上关闭线程池
 */
private static void shutdownNowThreadPool() {
    ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);
    pool.schedule(new Runnable() {
        @Override
        public void run() {
            System.out.println("我是执行结果...");
        }
    }, 1, TimeUnit.SECONDS);
    pool.shutdownNow();
}

//没有输出结果,因为任务被取消了

总结

频繁使用线程必须使用线程池,避免线程的频繁创建和销毁带来的资源消耗。本篇,我们讲解了快捷创建线程池的Api。下一篇,我们再讲解线程池具体参数的自定义。

上一篇 下一篇

猜你喜欢

热点阅读