java线程池介绍(一)

来源:互联网 发布:我是歌手网络直播地址 编辑:程序博客网 时间:2024/05/01 05:04

今天看了一下java并发包中的API,这里做一个总结。
首先我们先看一下,java线程池相关的类以及他们的关系uml图
这里写图片描述
从类图和源码中可以了解到,Executors类是提供线程池创建的类,而实现Executo接口系列的类则是提供线程池所有用的行为。例如execute、submit、shutDown等
Executors类中提供四种创建线程池的静态方法。

创建线程池的几种方式

创建缓存线程池

  • 创建可缓存的线程池,如果没有可用的线程,会创建一个新的,并销毁超过60s没有重用的线程
public static void newCachedThreadPool(){        MyRunnable myRunnable = new MyRunnable();        ExecutorService executorService = Executors.newCachedThreadPool();        for (int i = 0; i < 5; i++) {            executorService.execute(myRunnable);        }        executorService.shutdown();    }

创建固定数量的线程池

  • 创建固定线程数的线程池
 public static void newFixedThreadPool(){        MyRunnable myRunnable = new MyRunnable();        ExecutorService executorService = Executors.newFixedThreadPool(5);        for (int i = 0; i < 5; i++) {            executorService.execute(myRunnable);        }        executorService.shutdown();    }

创建单一线程的线程池

  • 创建一个单线程化的Executor。
public static void newSingleThreadExecutor(){        MyRunnable myRunnable = new MyRunnable();        ExecutorService executorService = Executors.newSingleThreadExecutor();        for (int i = 0; i < 5; i++) {            executorService.execute(myRunnable);        }        executorService.shutdown();    }

创建具有周期性的线程池

    public static void newSchduleThreadExecutor(){        MyRunnable myRunnable = new MyRunnable();        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);        for (int i = 0; i < 5; i++) {            executorService.execute(myRunnable);        }        executorService.shutdown();    }

对源码进行的一番分析

通过查看Executors的源码可以了解到其中newCachedThreadPool()和newFixedThreadPool(int nThreads)创建多线程的方法其实是交给ThreadPoolExecutor来执行的。

 public static ExecutorService newFixedThreadPool(int nThreads) {        return new ThreadPoolExecutor(nThreads, nThreads,                                      0L, TimeUnit.MILLISECONDS,                                      new LinkedBlockingQueue<Runnable>());    }public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                      60L, TimeUnit.SECONDS,                                      new SynchronousQueue<Runnable>());    }

ThreadPoolExecutor的构造方法有以下参数说明:
corePoolSize 核心线程数
maximumPoolSize 允许的最大线程数
keepAliveTime 单个线程存或时间
TimeUnit 持续时间的单位
BlockingQueue 任务执行前保持任务的队列

我们可以根据ThreadPoolExecutor提供的构造方法来自定义线程池

 //创建等待队列        BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(10);        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, blockingQueue);        for (int i = 0; i <10 ; i++) {            threadPoolExecutor.submit(new MyCallable<String>());        }        threadPoolExecutor.shutdown();

ExecutorService的行为方法

通过Executors创建方式可以查看到,newCachedThreadPool和newFixedThreadPool线程池的创建返回对象是ExecutorService,这是一个提供线程池操作的接口。
它的execute()和submit方法值得我们了解一下
从线程池的继承结构来看,它们都继承Executor接口,该接口只提供一个方法

void execute(Runnable command);

因此所有创建的线程池都会有execute的方法实现,ExecutorService还提供了不同的submit方法和终止线程的shutdown方法

//带Future返回值的submit方法。 <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result);     Future<?> submit(Runnable task);     //结束多线程的执行     void shutdown();

我们看到ExecutorService提供的submit中传入的参数有两类,一类是Runnable,另一类是Callable。Runnable大家都很熟悉了,是创建多线程提供的接口方法。我们可以通过实现Runnable接口来实现一个多线程要执行的run方法。但是这个run方法没有返回值,而Calleable接口与Runnable类似,唯一不同的就是它有返回值

@FunctionalInterfacepublic interface Callable<V> {    V call() throws Exception;}@FunctionalInterfacepublic interface Runnable {    public abstract void run();}

Callable接口

从这里我们就看出ExecutorService的submit的区别了,
一个传入Callable参数的submit方法可以有返回值,
传入Runnable参数的submit方法没有返回值。
我们可以通过例子看下Callable的用法

public static void callableSubmitTest() throws ExecutionException, InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        List<Future<String>> list = new ArrayList<Future<String>>();        for (int i = 0; i <10 ; i++) {            Future<String> future = executorService.submit(new MyCallable<String>());            list.add(future);        }        for (int i = 0; i < list.size(); i++){            Future<String> future = list.get(i);            System.out.println("future.get() = " + future.get() + " is canceled :" + future.isDone());        }        executorService.shutdown();    }    static class MyCallable<String> implements Callable<String>{        public String call() throws Exception {            System.out.println(Thread.currentThread().getName() + " 线程名...");            return (String) Thread.currentThread().getName();        }    }

Future

ExecutorService的submit都返回了Future对象,而这个对象是做什么用的呢?
Future也是一个接口类,这里面定义了多线程任务的完成状态。
例如isCanceled()、isDone()等等这些方法,用于判断多线程任务的执行状态。
通过Future的get()方法获取Callable返回的结果。

//在任务完成之前结束,返回trueboolean isCancelled();//在任务完成后,返回trueboolean isDone();//获取结果值V get();

还有一个ScheduleExecutorService的方法没有进行介绍,下一次再与大家分享!
参考博客:
http://wiki.jikexueyuan.com/project/java-concurrency/executor.html
代码例子:
https://github.com/hpulzl/lzl_workspace/tree/master/thread_demo

原创粉丝点击