进阶9_多线程3_线程池的基本

来源:互联网 发布:淘宝灯笼是什么意思 编辑:程序博客网 时间:2024/05/18 16:15

进阶9_多线程3 线程池


无论是Runable还是Thread我们都是在需要的时候直接开启线程,这难免会有很多线程对象的浪费。并且我们也无法管理到我们的线程,也不能让我们的线程能够按照我们想要的顺序去执行。这里java就提出了线程池的概念。

线程池的优点

  • 减少线程对象的创建、销毁的开销
  • 控制并发线程数目,提高效率,更好的避免因争抢资源导致的阻塞
  • 更好的管理线程 定期执行,控制数量等。

线程的顶级接口

ExecutorService

这里ExecutorService还继承了Exeutor接口,里面有一个execute方法

所有的线程池都实现了这个接口

ExecutorService的实现类

  • ThreadPoolExecutor
  • ScheduleThreadPoolExecutor

ThreadPoolExecutor是常用的线程池实现类,而后者则主要是处理周期性任务。

线程池的实例化

不会使用new的形势创建线程池,这里JDK提供乐意个工厂类来完成线程池的创建。

Executors 创建线程池

四种创建模式

  1. newFixedThreadPool(int)
  2. newSingleThreadExecutor
  3. newCachedThreadPool()
  4. newScheduledThreadPool(int)

这是常用的,当然实际上是这样的 :

这里多为重载,重载中要求有ThreadFactory,一个线程工厂,一般可以不操作。

启动指定数量的线程

很多人认为线程只要设备能吃得消,就越多越好,当然确实是这样,但是毕竟安卓设备的配置几乎都不一样,所以滥用线程首先对象过多,其次过多的创建销毁也会消耗不少资源不是一个最佳的实现,通过这个线程池我们可以指定启动的线程数,来完成指定的任务,而不是无休止的创建线程。

newFixedThreadPool(int)

public static void main(String[] args) throws InterruptedException, ExecutionException {    // 创建一个有三个线程的线程池    ExecutorService service = Executors.newFixedThreadPool(3);    // 创建10个任务    for (int i = 0; i < 10; i++) {        final int temp = i;        Future<Integer > future = service.submit(new Callable<Integer>() {            @Override            public Integer call() throws Exception {                // TODO Auto-generated method stub                System.out.print(Thread.currentThread().getName()                        + "正在执行任务\t");                return temp;            }        });        System.out.println(future.get()+"执行完成");    }}

这里通过工厂创建了一个只有三个线程的线程池,但是却有10个任务需要完成,但是不会创建十个线程对象,而是将这十个任务交给这个三个线程对象来完成。所以结果是这样的

10个任务分别被1、2、3线程完成了。当然这里也可以看到Future和Callable的好处。

newCachedThreadPool

一种带有缓冲效果的线程池。当线程中有已经完成的任务的线程,并且还有一些没有完成的任务的时候,不会重复创建线程,而是将已经完成任务的线程用来执行没有完成的任务。

public static void main(String[] args) throws InterruptedException, ExecutionException {    // 创建一个有三个线程的线程池    ExecutorService service = Executors.newCachedThreadPool();    // 创建10个任务    for (int i = 0; i < 10; i++) {        final int temp = i;        Future<Integer > future = service.submit(new Callable<Integer>() {            @Override            public Integer call() throws Exception {                // TODO Auto-generated method stub                System.out.print(Thread.currentThread().getName()                        + "正在执行任务\t");                return temp;            }        });        System.out.println(future.get()+"执行完成");    }}

这里是开启了两根线程,原因是为了更好的执行,当没有空闲的线程的时候就会创建新的线程,当有空闲的线程就复用。所以这里这个程序的执行结果不唯一。

newScheduledThreadPool

执行定时性任务

public static void main(String[] args) {    ScheduledExecutorService scheduledThreadPool = Executors            .newScheduledThreadPool(5);    // 第二个参数为延迟的时间 第三个参数代表即时的方式以秒    scheduledThreadPool.schedule(new Runnable() {        public void run() {            System.out.println("delay 3 seconds");        }    }, 3, TimeUnit.SECONDS);}

还可以周期性执行

public static void main(String[] args) {    ScheduledExecutorService scheduledThreadPool = Executors            .newScheduledThreadPool(5);    scheduledThreadPool.scheduleAtFixedRate(new Runnable() {        public void run() {            System.out.println("delay 3 seconds");        }    },1, 2, TimeUnit.SECONDS);}

代表延后1秒,2秒为一个周期重复执行。

newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务

public static void main(String[] args) {    ExecutorService singleThreadExecutor = Executors            .newSingleThreadExecutor();    for (int i = 0; i < 10; i++) {        final int index = i;        singleThreadExecutor.execute(new Runnable() {            public void run() {                try {                    System.out.println(Thread.currentThread().getName()+"="+index);                    Thread.sleep(2000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });    }}

这里会顺序输出0-9,并且只有一个线程在完成这样的操作。

原创粉丝点击