(转)java线程池的使用

服务器应用程序经常需要处理执行时间很短而数目巨大的请求, 如果为每一个请求创建一个新的线程, 会导致一些问题的出现, 如:

1. 性能瓶颈. 线程的创建和销毁需要执行大量的后台操作, 如果单个请求的执行时间很短, 有可能花在创建和销毁线程上的时间大于真正执行请求的时间.

2. 可能会导致资源不足. 大量的并发请求意味着需要创建大量的线程, 过多的线程存在会吞噬大量的系统资源, 而且CPU需要在这些线程间不断切换, 这可能引发"切换过度"的问题.

为了适应上述场合, java在JDK1.5中引入了线程池的概念. 线程池中存放着一定数量的已创建好的线程, 当一个请求到来时, 只需从线程池中取出一个线程来执行请求, 请求完成后再将线程归还给线程池. 同时, 我们可以为线程池指定最大的线程数量, 当池中所有线程都处于活动状态下, 新的任务会排队等候, 直到之前的某个任务处理完成后, 新的任务才能得到处理.

创建线程池. java.util.concurrent.Executors类提供了多个静态方法用于创建线程池.

|--public static ExecutorService newFixedThreadPool(int nThreads): 创建一个可重用的固定线程数的线程池. 如果池中所有的nThreads个线程都处于活动状态时提交任务(任务通常是Runnable或Callable对象), 任务将在队列中等待, 直到池中出现可用线程.

|--public static ExecutorService newCachedThreadPool(): 调用此方法创建的线程池可根据需要自动调整池中线程的数量. 执行任务时将重用存在先前创建的线程(如果池中存在可用线程的话). 如果池中没有可用线程, 将创建一个新的线程, 并将其添加到池中. 池中的线程超过60秒未被使用就会被销毁, 因此长时间保持空闲的CachedThreadPool不会消耗额外的资源.

|--public static ExecutorService newSingleThreadExecutor(): 创建一个单线程的Executor. 这个Executor保证按照任务提交的顺序依次执行任务.

|--public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize): 创建一个可重用的固定线程数的线程池. ScheduledExecutorService是ExecutorService的子接口, 调用ScheduledExecutorService的相关方法, 可以延迟或定期执行任务.

以上静态方法均使用默认的ThreadFactory(即Executors.defaultThreadFactory()方法的返回值)创建线程, 如果想要指定ThreadFactory, 可调用他们的重载方法.通过指定ThreadFactory, 可以定制新建线程的名称, 线程组, 优先级, 守护线程状态等.

如果Executors提供的创建线程池的方法无法满足要求, 可以使用ThreadPoolExecutor类创建线程池.

提交任务. 所有的线程池都是ExecutorService及其子类的对象, 因此, 可以调用ExecutorService的相关方法提交任务.

|--void execute(Runnable command): 使用池中已存在的线程或新建一个线程执行command.

01 public class ExecutorsDemo {
02      
03     public static void main(String[] args) throws Exception {
04         System.out.println("----------------FixedThreadPool---------------------");
05         ExecutorService fixedPool = getFixedThreadPool();
06         executeThread(fixedPool);
07          
08         // 为了避免混淆, 需要等待executeThread(fixedPool)执行完成
09         Thread.sleep(3000);
10          
11         System.out.println("----------------CashedThreadPool---------------------");
12         ExecutorService cashedPool = getCashedThreadPool();
13         executeThread(cashedPool);
14          
15         // 为了避免混淆, 需要等待executeThread(cashedPool)执行完成
16         Thread.sleep(3000);
17          
18         System.out.println("----------------SingleThreadExecutor---------------------");
19         ExecutorService singleExecutor = getSingleThreadExecutor();
20         executeThread(singleExecutor);
21          
22     }
23      
24     // 只存在一个线程的线程池
25     private static ExecutorService getSingleThreadExecutor() {
26         return Executors.newSingleThreadExecutor();
27     }
28  
29     // 创建一个根据需要自动调整大小的线程池
30     private static ExecutorService getCashedThreadPool() {
31         return Executors.newCachedThreadPool();
32     }
33  
34     // 创建一个可重用的固定线程数的线程池
35     private static ExecutorService getFixedThreadPool() {
36         return Executors.newFixedThreadPool(2);
37     }
38      
39     private static void executeThread(ExecutorService pool) {
40         Thread t1 = new MyThread();
41         Thread t2 = new MyThread();
42         Thread t3 = new MyThread();
43         Thread t4 = new MyThread();
44         // 将Tread放入线程池中执行
45         // MyThread类继承自Thread, 而Thread类实现了Runnable接口
46         pool.execute(t1);
47         pool.execute(t2);
48         pool.execute(t3);
49         pool.execute(t4);
50         // 关闭线程池
51         pool.shutdown();
52     }
53      
54     private static final class MyThread extends Thread {
55         @Override
56         public void run() {
57             super.run();
58             System.out.println(Thread.currentThread().getName() + ": is running!");
59         }
60     }
61 }

程序的输出为:

----------------FixedThreadPool---------------------

pool-1-thread-1: is running!

pool-1-thread-2: is running!

pool-1-thread-2: is running!

pool-1-thread-1: is running!

----------------CashedThreadPool---------------------

pool-2-thread-1: is running!

pool-2-thread-2: is running!

pool-2-thread-4: is running!

pool-2-thread-3: is running!

----------------SingleThreadExecutor---------------------

pool-3-thread-1: is running!

pool-3-thread-1: is running!

pool-3-thread-1: is running!

pool-3-thread-1: is running!

|--Future<T> submit(Callable<T> task): 使用池中已存在的线程或新建一个线程执行task, 与execute()方法不同的是, 该方法会返回线程的执行结果. submit方法接受一个Callable<T>对象, Callable<T>接口是一个泛型接口, 实现Callable<T>接口需要重写其中的call()方法, call()方法将返回一个T对象. submit方法的返回值是Future<T>对象, 调用该对象的get()可以获得call()方法的返回值.

01 public class FutureDemo {
02     public static void main(String[] args) throws Exception {
03         ExecutorService pool = Executors.newFixedThreadPool(2);
04          
05         Future<Integer> intFuture = pool.submit(new IntegerCallable());
06         Integer returnInt = intFuture.get();
07         System.out.println("返回值为" + returnInt);
08          
09         Future<Boolean> boolFuture = pool.submit(new BooleanCallable());
10         Boolean returnBool = boolFuture.get();
11         System.out.println("返回值为" + returnBool);
12          
13         pool.shutdown();
14     }
15      
16     private final static class IntegerCallable implements Callable<Integer> {
17         // call()方法的返回值类型由泛型决定 
18         @Override
19         public Integer call() throws Exception {
20             return 2;
21         }
22     }
23      
24     private final static class BooleanCallable implements Callable<Boolean> {
25         @Override
26         public Boolean call() throws Exception {
27             return true;
28         }
29     }
30 }

程序的输出结果为:

返回值为2

返回值为true

|--List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks): 批量执行多个任务.

关闭线程池. 使用完线程池后需要关闭它, 否则程序可能一直处于运行状态. ExecutorService提供了2个方法用于关闭线程池:

|--void shutdown(): 关闭线程池, 不再接受新任务. 如果存在正在执行的任务, 则等待任务执行完成.

|--List<RunnableshutdownNow(): 关闭线程池, 不再接受新任务. 尽力尝试停止正在执行的任务, 并返回正在等待的任务列表.

|--boolean isShutdown(): 判断线程池是否已经关闭.

转自:http://coolxing.iteye.com/blog/1236588

服务器应用程序经常需要处理执行时间很短而数目巨大的请求, 如果为每一个请求创建一个新的线程, 会导致一些问题的出现, 如:

1. 性能瓶颈. 线程的创建和销毁需要执行大量的后台操作, 如果单个请求的执行时间很短, 有可能花在创建和销毁线程上的时间大于真正执行请求的时间.

2. 可能会导致资源不足. 大量的并发请求意味着需要创建大量的线程, 过多的线程存在会吞噬大量的系统资源, 而且CPU需要在这些线程间不断切换, 这可能引发"切换过度"的问题.

为了适应上述场合, java在JDK1.5中引入了线程池的概念. 线程池中存放着一定数量的已创建好的线程, 当一个请求到来时, 只需从线程池中取出一个线程来执行请求, 请求完成后再将线程归还给线程池. 同时, 我们可以为线程池指定最大的线程数量, 当池中所有线程都处于活动状态下, 新的任务会排队等候, 直到之前的某个任务处理完成后, 新的任务才能得到处理.

创建线程池. java.util.concurrent.Executors类提供了多个静态方法用于创建线程池.

|--public static ExecutorService newFixedThreadPool(int nThreads): 创建一个可重用的固定线程数的线程池. 如果池中所有的nThreads个线程都处于活动状态时提交任务(任务通常是Runnable或Callable对象), 任务将在队列中等待, 直到池中出现可用线程.

|--public static ExecutorService newCachedThreadPool(): 调用此方法创建的线程池可根据需要自动调整池中线程的数量. 执行任务时将重用存在先前创建的线程(如果池中存在可用线程的话). 如果池中没有可用线程, 将创建一个新的线程, 并将其添加到池中. 池中的线程超过60秒未被使用就会被销毁, 因此长时间保持空闲的CachedThreadPool不会消耗额外的资源.

|--public static ExecutorService newSingleThreadExecutor(): 创建一个单线程的Executor. 这个Executor保证按照任务提交的顺序依次执行任务.

|--public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize): 创建一个可重用的固定线程数的线程池. ScheduledExecutorService是ExecutorService的子接口, 调用ScheduledExecutorService的相关方法, 可以延迟或定期执行任务.

以上静态方法均使用默认的ThreadFactory(即Executors.defaultThreadFactory()方法的返回值)创建线程, 如果想要指定ThreadFactory, 可调用他们的重载方法.通过指定ThreadFactory, 可以定制新建线程的名称, 线程组, 优先级, 守护线程状态等.

如果Executors提供的创建线程池的方法无法满足要求, 可以使用ThreadPoolExecutor类创建线程池.

提交任务. 所有的线程池都是ExecutorService及其子类的对象, 因此, 可以调用ExecutorService的相关方法提交任务.

|--void execute(Runnable command): 使用池中已存在的线程或新建一个线程执行command.

01 public class ExecutorsDemo {
02      
03     public static void main(String[] args) throws Exception {
04         System.out.println("----------------FixedThreadPool---------------------");
05         ExecutorService fixedPool = getFixedThreadPool();
06         executeThread(fixedPool);
07          
08         // 为了避免混淆, 需要等待executeThread(fixedPool)执行完成
09         Thread.sleep(3000);
10          
11         System.out.println("----------------CashedThreadPool---------------------");
12         ExecutorService cashedPool = getCashedThreadPool();
13         executeThread(cashedPool);
14          
15         // 为了避免混淆, 需要等待executeThread(cashedPool)执行完成
16         Thread.sleep(3000);
17          
18         System.out.println("----------------SingleThreadExecutor---------------------");
19         ExecutorService singleExecutor = getSingleThreadExecutor();
20         executeThread(singleExecutor);
21          
22     }
23      
24     // 只存在一个线程的线程池
25     private static ExecutorService getSingleThreadExecutor() {
26         return Executors.newSingleThreadExecutor();
27     }
28  
29     // 创建一个根据需要自动调整大小的线程池
30     private static ExecutorService getCashedThreadPool() {
31         return Executors.newCachedThreadPool();
32     }
33  
34     // 创建一个可重用的固定线程数的线程池
35     private static ExecutorService getFixedThreadPool() {
36         return Executors.newFixedThreadPool(2);
37     }
38      
39     private static void executeThread(ExecutorService pool) {
40         Thread t1 = new MyThread();
41         Thread t2 = new MyThread();
42         Thread t3 = new MyThread();
43         Thread t4 = new MyThread();
44         // 将Tread放入线程池中执行
45         // MyThread类继承自Thread, 而Thread类实现了Runnable接口
46         pool.execute(t1);
47         pool.execute(t2);
48         pool.execute(t3);
49         pool.execute(t4);
50         // 关闭线程池
51         pool.shutdown();
52     }
53      
54     private static final class MyThread extends Thread {
55         @Override
56         public void run() {
57             super.run();
58             System.out.println(Thread.currentThread().getName() + ": is running!");
59         }
60     }
61 }

程序的输出为:

----------------FixedThreadPool---------------------

pool-1-thread-1: is running!

pool-1-thread-2: is running!

pool-1-thread-2: is running!

pool-1-thread-1: is running!

----------------CashedThreadPool---------------------

pool-2-thread-1: is running!

pool-2-thread-2: is running!

pool-2-thread-4: is running!

pool-2-thread-3: is running!

----------------SingleThreadExecutor---------------------

pool-3-thread-1: is running!

pool-3-thread-1: is running!

pool-3-thread-1: is running!

pool-3-thread-1: is running!

|--Future<T> submit(Callable<T> task): 使用池中已存在的线程或新建一个线程执行task, 与execute()方法不同的是, 该方法会返回线程的执行结果. submit方法接受一个Callable<T>对象, Callable<T>接口是一个泛型接口, 实现Callable<T>接口需要重写其中的call()方法, call()方法将返回一个T对象. submit方法的返回值是Future<T>对象, 调用该对象的get()可以获得call()方法的返回值.

01 public class FutureDemo {
02     public static void main(String[] args) throws Exception {
03         ExecutorService pool = Executors.newFixedThreadPool(2);
04          
05         Future<Integer> intFuture = pool.submit(new IntegerCallable());
06         Integer returnInt = intFuture.get();
07         System.out.println("返回值为" + returnInt);
08          
09         Future<Boolean> boolFuture = pool.submit(new BooleanCallable());
10         Boolean returnBool = boolFuture.get();
11         System.out.println("返回值为" + returnBool);
12          
13         pool.shutdown();
14     }
15      
16     private final static class IntegerCallable implements Callable<Integer> {
17         // call()方法的返回值类型由泛型决定 
18         @Override
19         public Integer call() throws Exception {
20             return 2;
21         }
22     }
23      
24     private final static class BooleanCallable implements Callable<Boolean> {
25         @Override
26         public Boolean call() throws Exception {
27             return true;
28         }
29     }
30 }

程序的输出结果为:

返回值为2

返回值为true

|--List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks): 批量执行多个任务.

关闭线程池. 使用完线程池后需要关闭它, 否则程序可能一直处于运行状态. ExecutorService提供了2个方法用于关闭线程池:

|--void shutdown(): 关闭线程池, 不再接受新任务. 如果存在正在执行的任务, 则等待任务执行完成.

|--List<RunnableshutdownNow(): 关闭线程池, 不再接受新任务. 尽力尝试停止正在执行的任务, 并返回正在等待的任务列表.

|--boolean isShutdown(): 判断线程池是否已经关闭.

转自:http://coolxing.iteye.com/blog/1236588

时间: 2024-11-01 17:44:10

(转)java线程池的使用的相关文章

Java线程池应用

Executors工具类用于创建Java线程池和定时器. newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程.在任意点,在大多数 nThreads 线程会处于处理任务的活动状态.如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待.如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要).在某个线程被显式地关闭之前,池中的线程将一直存在. 创建一个固定大小的线程池来执

java线程池

1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? 1 new Thread(new Runnable() { 2 3 @Override 4 public void run() { 5 // TODO Auto-generated method stub 6 } 7 }).start(); 那你就out太多了,new Thread的弊端如下: a. 每次new Thread新建对象性能差. b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过

Java线程池使用说明

Java线程池使用说明 一 简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用.为我们在开发中处理线程的问题提供了非常大的帮助. 二:线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量.     根 据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少

Java 线程池的原理与实现

最近在学习线程池.内存控制等关于提高程序运行性能方面的编程技术,在网上看到有一哥们写得不错,故和大家一起分享. [分享]Java 线程池的原理与实现 这几天主要是狂看源程序,在弥补了一些以前知识空白的同时,也学会了不少新的知识(比如 NIO),或者称为新技术吧.线程池就是其中之一,一提到线程,我们会想到以前<操作系统>的生产者与消费者,信号量,同步控制等等.一提到池,我们会想到数据库连接池,但是线程池又如何呢? 建议:在阅读本文前,先理一理同步的知识,特别是syncronized同步关键字的用

Java 线程池学习

Reference: <创建Java线程池>[1],<Java线程:新特征-线程池>[2], <Java线程池学习>[3],<线程池ThreadPoolExecutor使用简介>[4],<Java5中的线程池实例讲解>[5],<ThreadPoolExecutor使用和思考>[6] [1]中博主自己通过ThreadGroup实现一个线程池(挺方便理解的),使用的是jdk1.4版本,Jdk1.5版本以上提供了现成的线程池. [2]中介绍

JAVA线程池的分析和使用

http://www.infoq.com/cn/articles/java-threadPool/ 1. 引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行.第三:提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控.但是要做到合理的利用线程池,必须对其原理了如指掌. 2. 线程池

java线程池分析和应用

比较 在前面的一些文章里,我们已经讨论了手工创建和管理线程.在实际应用中我们有的时候也会经常听到线程池这个概念.在这里,我们可以先针对手工创建管理线程和通过线程池来管理做一个比较.通常,我们如果手工创建线程,需要定义线程执行对象,它实现的接口.然后再创建一个线程对象,将我们定义好的对象执行部分装载到线程中.对于线程的创建.结束和结果的获取都需要我们来考虑.如果我们需要用到很多的线程时,对线程的管理就会变得比较困难.我们手工定义线程的方式在时间和空间效率方面会存在着一些不足.比如说我们定义好的线程

Java线程池:ExecutorService,Executors

简单的Java线程池可以从Executors.newFixedThreadPool( int n)获得.此方法返回一个线程容量为n的线程池.然后ExecutorService的execute执行之. 现给出一个示例. package zhangphil.executorservice; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ZhangPhil

JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue .

从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.ThreadPoolExecutor 就是这样的线程池.以下是我的学习过程. 首先是构造函数签名如下: [java] view plain copy print ? public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<

Java线程池使用和分析(二) - execute()原理

相关文章目录: Java线程池使用和分析(一) Java线程池使用和分析(二) - execute()原理 execute()是 java.util.concurrent.Executor接口中唯一的方法,JDK注释中的描述是“在未来的某一时刻执行命令command”,即向线程池中提交任务,在未来某个时刻执行,提交的任务必须实现Runnable接口,该提交方式不能获取返回值.下面是对execute()方法内部原理的分析,分析前先简单介绍线程池有哪些状态,在一系列执行过程中涉及线程池状态相关的判断