线程池

来源:互联网 发布:策略经营单机手游 知乎 编辑:程序博客网 时间:2024/05/29 19:31

概述

  程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
  线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

使用方式

  Java通过Executors提供四种线程池,分别为:
    newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
    newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

带缓存的线程池

public static void main(String[] args) {    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();    for (int i = 0; i < 10; i++) {        final int nIndex = i;        try {            Thread.sleep(500);        } catch (InterruptedException e) {            e.printStackTrace();        }        cachedThreadPool.execute(new Runnable() {            public void run() {                System.out.println(Thread.currentThread().getName() + " " + nIndex);                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });     // 结束线程     cachedThreadPool.shutdown();    }}

     线程池_1
  首先程序第一次执行到new Runnable()时候创建了一个线程(thread-1,图中第一行),第一个线程打印信息结束后开始进入1秒的睡眠。
  然后,第二个次new Runnable()时候由于第二次到达这里的时间只经过了500毫秒时间,此时,第一个线程还正在睡眠中,这时线程池当前是没有空闲的线程,所以,就创建了第二个线程(thread-2,图中第二行)。
  然后,第三次走到new Runnable()时候有经过了500毫秒的时间,此时第一个线程已经完成了睡眠退出了运行,而此时,线程池判断已经又一个线程对象是空闲的了,所以就复用这个线程来执行新的Runnable接口实现对象,所以这里没有直接出现thread-3而还是thread-1。
  最后,出现thread-3的时候也是一样的是因为刚好thread-1和thread-2都在睡眠没有释放资源所造成的。

固定长度的线程池

public static void main(String[] args) {    ExecutorService cachedThreadPool = Executors.newFixedThreadPool(3);    for (int i = 0; i < 10; i++) {        final int nIndex = i;        cachedThreadPool.execute(() -> {            System.out.println(Thread.currentThread().getName() + " " + nIndex);            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        });    }    cachedThreadPool.shutdown();}

线程池_2
  无论new Runnable()都始终只有3个线程。定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

延时或定时线程池

  线程池还可以延时或者定期发送的方式执行,这种线程池也是固定长度的线程池,代码如下:

// 延迟启动public static void main(String[] args) {    ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);    for (int i = 0; i < 10; i++) {        ses.schedule(new Runnable() {            @Override            public void run() {                System.out.println("延迟3秒");            }        }, 3, TimeUnit.SECONDS);    }    // ses.shutdown();}// 定时启动public static void main(String[] args) {    ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);    for (int i = 0; i < 10; i++) {        ses.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                System.out.println("1秒后每三秒执行一次  " + Thread.currentThread().getName());            }        }, 1, 3, TimeUnit.SECONDS);    }    // ses.shutdown();}

单一任务线程池

  这种线程只会复用一个工作线程,确保任务是按照顺序依次执行,代码如下:

public static void main(String[] args) {    ExecutorService executorService = Executors.newSingleThreadExecutor();    for (int i = 0; i < 10000; i++) {        final int nIndex = i;        executorService.execute(new Runnable() {            @Override            public void run() {                System.out.println("线程 " + nIndex + " " + Thread.currentThread().getName());            }        });    }}

           以上是关于线程池使用方式的学习和理解!