【Java进阶】Java多线程之线程池浅析

此文章接着上篇文章:Java多线程概念浅析
本篇博客包含如下内容:

  • 为何有线程池?Java对线程池的支持?
  • 线程池实例!
  • 线程池不同创建方式的意义?
  • 何时使用线程池?

为何有线程池?

为何有线程池?

  • 上篇文章中提到线程的创建和简单的解析,但是我们会发现,我们必须要为每一任务都建立一个线程。
  • 因此对于大量的任务而言这不是高效的,为每个任务建立线程可能会限制流量并且造成性能的降低。
  • 线程池则为我们提供了管理并发的执行多个任务的理想方法?

对于线程池任务和线程管理在Java中提供的方法!

  • 再简单理解任务与线程:任务是Runnable接口的实例,线程的本质是便于任务执行的对象。
  • Java提供Executor接口来执行线程池中的任务
  • 提供ExecutorService接口来管理和控制任务
  • ExecutorService是Executor的子接口
  • 创建执行线程池中的任务(Executor)的对象,使用Executors类中的静态方法newFixedThreadPool(numberOfThreads:int):ExecutorService和newCachedThreadPool():ExecutorService

两个接口的源码学习

Executor接口:

package java.util.concurrent;

public interface Executor {
    void execute(Runnable arg0);
}

ExecutorService接口:

package java.util.concurrent;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public interface ExecutorService extends Executor {
    void shutdown();

    List<Runnable> shutdownNow();

    boolean isShutdown();

    boolean isTerminated();

    boolean awaitTermination(long arg0, TimeUnit arg2) throws InterruptedException;

    <T> Future<T> submit(Callable<T> arg0);

    <T> Future<T> submit(Runnable arg0, T arg1);

    Future<?> submit(Runnable arg0);

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> arg0) throws InterruptedException;

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> arg0, long arg1, TimeUnit arg3)
            throws InterruptedException;

    <T> T invokeAny(Collection<? extends Callable<T>> arg0) throws InterruptedException, ExecutionException;

    <T> T invokeAny(Collection<? extends Callable<T>> arg0, long arg1, TimeUnit arg3)
            throws InterruptedException, ExecutionException, TimeoutException;
}

几个重要方法解析:

所属接口/类方法解析
ExecutorsnewFixedThreadPool(int numberOfThreads):ExecutorService创建一个可并发执行固定数目线程的线程池
……newCachedThreadPool():ExecutorService创建一个可按需改变可执行线程数的线程池
Executorexecute(Runnable object):void执行传入的任务,子接口都实现此方法
ExecutorServicesubmit()向线程池提交任务
……shutdown():void关闭执行器,但允许完成完成执行器中的任务,一旦关闭不能接受新任务
……shutdownNow():List立即关闭,不管是否存在未完成的任务,返回未完成的清单
……isShutdown():boolean如果执行器已经关闭则返回true
……isTerminated():boolean如果线程池中所有任务都被终止则返回true

线程池实例

任务代码参考:Java多线程概念浅析

线程池代码:

package executors;

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

import thread.RunnableImp1;
import thread.RunnableImp2;

public class ExecutorDemo {
    public static void main(String[] args) {

        // 创建指定最大线程数的线程池执行器
        ExecutorService executor = Executors.newFixedThreadPool(3);

        // 创建任务并添加到线程池,执行器会主动创建这三个任务
        executor.execute(new RunnableImp1('a',100));
        executor.execute(new RunnableImp1('b',100));
        executor.execute(new RunnableImp2(100));

        // 关闭执行器
        executor.shutdown();
        // 执行器是否已经关闭
        boolean isClose = executor.isShutdown();
        // 换行
        System.out.println();
        System.out.println(isClose);
    }
}

输出:

aaaaabb1  a2  b3  a4  b5  a6  b7  a8aaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaab
执行器结束?-true

如果将:

ExecutorService executor = Executors.newFixedThreadPool(3);

中的3改为1,输出结果是?

  • 这三个任务线程会顺序执行,因为只有一个可执行线程!下个任务会等待上个任务执行完重用此线程。

线程池不同创建方式的意义

  • newFixedThreadPool(int)创建:

    • 当使用此方法创建时,创建固定的可执行线程,如果线程完成了某个任务的执行,它可被重新使用以执行另外的任务。如果线程池中所有的线程都不是处于空闲状态。而且还有任务在等待执行,那么在关机之前,如果由于一个错误终止了一个线程,就会创建一个新的线程来替代它。
  • newCachedThreadPool()创建:

    • 当使用此方法创建时,创建的可执行线程是可变的。如果线程池中所有的线程都不是处于空闲状态。而且还有任务在等待执行,此方法会创建一个新线程。如果缓冲池中的线程在60秒内都没有被使用就该终止它。

何时使用线程池

  • 如果需要为一个任务创建一个线程、则使用Thread类,如果需要为多个任务创建线程,最好使用线程池。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值