java 线程池

http://www.importnew.com/8542.html

http://liuzl121.iteye.com/blog/1779039  

首先说下java实现多线程的两种方式,这个很多人应该都知道,简单的说说,一种是实现Runnable接口,另一种是继承Thread类,两个方法各有各的好处吧,实现Runnable接口的话可以做到多个线程之间的资源共享,同时java是单继承的,如果继承了Thread类就不能在继承其他类了,而实现了Runnable接口的话就可以同时继承其他类。而继承Thread类的优点呢是获取当前的线程信息比较简单,而我觉得继承Runnable接口的也不复杂,所有个人比较青睐用实现Runnable接口的这种方式。

       
        再说下线程池的原理,线程池会让我联想起数据库连接池,数据库连接池的作用就是给你个数据库连接,然后我们用这个连接去执行操作,而不论我们执行什么操作,数据库连接都不会与我们的逻辑耦合,像一个工具类一样;同样线程池也要满足这样的要求,与我们的逻辑解耦。实现解耦的话就要用到‘多态’或‘接口回调’,就是通过调用父类或接口中的方法从而间接地调用我们所要执行的代码。
        以上这些是思路吧,说说原理,不知道有没有人跟我一样,原来我一直以为线程池的话就是多个线程,某一个线程跑完了我们的逻辑方法就结束了,那既然结束了再怎么去接着执行别的任务,所以感觉多线程很难;其实多线程多线程就是通过线程调用线程实现的;打个比方来说就像“摆渡”,河的一岸有很多的人,他们想过河,过河的过程做什么就是他们自己的逻辑,只要他符合我的要求我就送你过河(线程池的要求就是实现Runnable或继承Thread类),然后我开了几条船去送人,只要河的这一岸有满足的人,我就送你过河。这个例子中河一岸的人就是我们要执行的任务,是一个集合,船就是线程池中的线程,由我们自己控制,过河这个动作就是要执行的逻辑,我们只负责把船调给你,怎么划桨怎么过河就是程序自己的逻辑了。



        可能说了这么多还是不是很清楚(原谅我的表达能力!),看一个生产者和消费者的例子,生产者不停的生产产品,生产后放入仓库,消费者不停的从仓库里拿产品。我们用线程池将他们实现。


        先是创建商品类,商品类中有商品信息:
Java代码   收藏代码
  1. /** 
  2.  * 产品类 
  3.  */  
  4. class Product {  
  5.     private String id;// 产品id  
  6.     private String name;// 产品名称  
  7.   
  8.     public Product(String id, String name) {  
  9.         this.id = id;  
  10.         this.name = name;  
  11.     }  
  12.   
  13.     @Override  
  14.     public String toString() {  
  15.         return "(产品ID:" + id + " 产品名称:" + name + ")";  
  16.     }  
  17.   
  18.     public String getId() {  
  19.         return id;  
  20.     }  
  21.   
  22.     public void setId(String id) {  
  23.         this.id = id;  
  24.     }  
  25.   
  26.     public String getName() {  
  27.         return name;  
  28.     }  
  29.   
  30.     public void setName(String name) {  
  31.         this.name = name;  
  32.     }  
  33.   
  34. }  



        然后创建仓库类,仓库对外开放两个方法,存入和取出,由于是多线程,所以要用synchronized关键字修饰这两个方法。
Java代码   收藏代码
  1. /** 
  2.  *仓库 
  3.  */  
  4. class Storage {  
  5.     // 仓库容量为10  
  6.     private Product[] products = new Product[10];  
  7.     private int top = 0;  
  8.   
  9.     // 生产者往仓库中放入产品  
  10.     public synchronized void push(Product product) {  
  11.         while (top == products.length) {  
  12.             try {  
  13.                 System.out.println("仓库满了");  
  14.                 wait();//仓库已满,等待  
  15.             } catch (InterruptedException e) {  
  16.                 // TODO Auto-generated catch block  
  17.                 e.printStackTrace();  
  18.             }  
  19.         }  
  20.         //把产品放入仓库  
  21.         products[top++] = product;  
  22.         System.out.println(Thread.currentThread().getName() + " 生产了产品"  
  23.                 + product);  
  24.         notifyAll();//唤醒等待线程  
  25.   
  26.     }  
  27.   
  28.     // 消费者从仓库中取出产品  
  29.     public synchronized Product pop() {  
  30.         while (top == 0) {  
  31.             try {  
  32.                 System.out.println("仓库空了");  
  33.                 wait();//仓库空,等待  
  34.             } catch (InterruptedException e) {  
  35.                 // TODO Auto-generated catch block  
  36.                 e.printStackTrace();  
  37.             }  
  38.   
  39.         }  
  40.   
  41.         //从仓库中取产品  
  42.         --top;  
  43.         Product p = new Product(products[top].getId(), products[top].getName());  
  44.         products[top] = null;  
  45.         System.out.println(Thread.currentThread().getName() + " 消费了产品" + p);  
  46.         notifyAll();//唤醒等待线程  
  47.         return p;  
  48.     }  
  49. }  



        然后生产者消费者的实例,实现Runnable接口,run方法中分别调用入库和出库的方法。
Java代码   收藏代码
  1. /** 
  2.  * 消费者 
  3.  */  
  4. class Consumer implements Runnable {  
  5.     private Storage storage;  
  6.   
  7.     public Consumer(Storage storage) {  
  8.         this.storage = storage;  
  9.     }  
  10.   
  11.     @Override  
  12.     public void run() {  
  13.         storage.pop();  
  14.     }  
  15. }  
  16.   
  17. /** 
  18.  * 生产者 
  19.  */  
  20. class Producer implements Runnable {  
  21.     private Storage storage;  
  22.   
  23.     public Producer(Storage storage) {  
  24.         this.storage = storage;  
  25.     }  
  26.   
  27.     @Override  
  28.     public void run() {  
  29.         Product product = new Product("090505105""电话");  
  30.         storage.push(product);  
  31.     }  
  32.   
  33. }  



        之后就是关键的线程池的实现,线程池首先是一个容器,放着执行的线程和待执行的任务,线程池也只有一个所以用单例的设计模式。对外公开存放作业的方法和设置最大线程数的方法,当外界有作业放进来的时候就执行,执行完了之后销毁。上代码。
Java代码   收藏代码
  1. package thread;  
  2. import java.util.Collections;  
  3. import java.util.Date;  
  4. import java.util.LinkedList;  
  5. import java.util.List;  
  6. import java.util.concurrent.Executor;  
  7.   
  8. import org.apache.log4j.Logger;  
  9.   
  10. /** 
  11. * 线程池 
  12. * 创建线程池,销毁线程池,添加新任务 
  13.  
  14. * @author obullxl 
  15. */  
  16. public final class ThreadPool {  
  17.      
  18.     /* 单例 */  
  19.     private static ThreadPool instance = ThreadPool.getInstance();  
  20.   
  21.     /* 默认池中线程数 */  
  22.     private static int worker_num = 5;  
  23.   
  24.     /* 等待任务队列 */  
  25.     private static List<Runnable> taskQueue = Collections  
  26.             .synchronizedList(new LinkedList<Runnable>());  
  27.     /* 池中的所有线程 */  
  28.     public PoolWorker[] workers;  
  29.   
  30.     /** 
  31.      * 构造器 
  32.      * */  
  33.     private ThreadPool() {  
  34.         workers = new PoolWorker[5];  
  35.         for (int i = 0; i < workers.length; i++) {  
  36.             workers[i] = new PoolWorker(i);  
  37.         }  
  38.     }  
  39.   
  40.     private ThreadPool(int pool_worker_num) {  
  41.         worker_num = pool_worker_num;  
  42.         workers = new PoolWorker[worker_num];  
  43.         for (int i = 0; i < workers.length; i++) {  
  44.             workers[i] = new PoolWorker(i);  
  45.         }  
  46.     }  
  47.   
  48.     /** 
  49.      * 修改最大线程数 
  50.      * */  
  51.     public void setMaxThreadNum(int max){  
  52.         worker_num = max;  
  53.     }  
  54.       
  55.     /** 
  56.      * 单例返回本对象 
  57.      * */  
  58.     public static synchronized ThreadPool getInstance() {  
  59.         if (instance == null)  
  60.             return new ThreadPool();  
  61.         return instance;  
  62.     }  
  63.     /** 
  64.     * 增加新的任务 
  65.     * @param newTask 
  66.     */  
  67.     public void addTask(Runnable newTask) {  
  68.         synchronized (taskQueue) {  
  69.             taskQueue.add(newTask);  
  70.             /*  开始执行 */  
  71.             this.startWork();  
  72.         }  
  73.     }  
  74.     /** 
  75.     * 批量增加新任务 
  76.     * @param taskes 
  77.     */  
  78.     public void batchAddTask(List<Runnable> taskes) {  
  79.         if (taskes == null || taskes.size() == 0) {  
  80.             return;  
  81.         }  
  82.         synchronized (taskQueue) {  
  83.             for (int i = 0; i < taskes.size(); i++) {  
  84.                 if (taskes.get(i) == null) {  
  85.                     continue;  
  86.                 }  
  87.                 taskQueue.add(taskes.get(i));  
  88.             }  
  89.             /* 唤醒队列, 开始执行 */  
  90. //            taskQueue.notifyAll();  
  91.         }  
  92.         for (int i = 0; i < taskes.size(); i++) {  
  93.             if (taskes.get(i) == null) {  
  94.                 continue;  
  95.             }  
  96.         }  
  97.         /*  开始执行 */  
  98.         this.startWork();  
  99.     }  
  100.       
  101.     /** 
  102.      * 执行作业 
  103.      * */  
  104.     private void startWork(){  
  105.         for (int i=0;i<workers.length;i++){  
  106.             if(!workers[i].isRunning){  
  107.                 workers[i].start();  
  108.             }  
  109.         }  
  110.     }  
  111.       
  112.       
  113.     /** 
  114.     * 销毁线程池 
  115.     */  
  116.     public synchronized void destroy() {  
  117.         for (int i = 0; i < worker_num; i++) {  
  118.             workers[i].stopWorker();  
  119.             workers[i] = null;  
  120.         }  
  121.         taskQueue.clear();  
  122.     }  
  123.   
  124.     /** 
  125.     * 池中工作线程 
  126.     *  
  127.     * @author obullxl 
  128.     */  
  129.     private class PoolWorker extends Thread {  
  130.         private int index = -1;  
  131.         /* 该工作线程是否有效 */  
  132.         private boolean isRunning = false;  
  133.         /* 该工作线程是否可以执行新任务 */  
  134.         private boolean isWaiting = true;  
  135.   
  136.         public PoolWorker(int index) {  
  137.             this.index = index;  
  138.         }  
  139.   
  140.         public void stopWorker() {  
  141.             this.isRunning = false;  
  142.         }  
  143.   
  144.         public boolean isWaiting() {  
  145.             return this.isWaiting;  
  146.         }  
  147.         /** 
  148.         * 循环执行任务 
  149.         * 这也许是线程池的关键所在 
  150.         */  
  151.         public void run() {  
  152.             isRunning = true;  
  153.             while (isRunning) {  
  154.                 Runnable r = null;  
  155.                 synchronized (taskQueue) {  
  156.                     if (taskQueue.isEmpty()) {  
  157.                         stopWorker();       //     (1) 没有作业就不执行  
  158. //                        try {                    (2) 没有作业就等待,知道有作业加进来  
  159. //                            /* 任务队列为空,则等待有新任务加入从而被唤醒 */  
  160. //                            taskQueue.wait(20);  
  161. //                        } catch (InterruptedException ie) {  
  162. //                            logger.error(ie);  
  163. //                        }  
  164.                     }else{  
  165.                     /* 取出任务执行 */  
  166.                         r = taskQueue.remove(0);  
  167.                     }  
  168.                 }  
  169.                 if (r != null) {  
  170.                     r.run();  
  171.                 }  
  172.                 isWaiting = true;  
  173.                 r = null;  
  174.             }  
  175.         }  
  176.     }  
  177. }  



        然后写一个main方法模拟调用
Java代码   收藏代码
  1. public class ProducersAndConsumers {  
  2.       
  3.     public static void main(String[] args) {  
  4.         ThreadPool pool = ThreadPool.getInstance();  
  5.         Storage storage = new Storage();  
  6.         List<Runnable> conTasks = new ArrayList<Runnable>();  
  7.   
  8.         for(int i=0;i<100;i++){  
  9.             Consumer con = new Consumer(storage);  
  10.             Producer pro = new Producer(storage);  
  11.             conTasks.add(con);  
  12.             conTasks.add(pro);  
  13.         }  
  14.           
  15.         pool.batchAddTask(conTasks);  
  16.   
  17.     }  
  18.       
  19. }  


         将线程池中待执行任务容器中放入任务,然后线程池开启5个线程,去调用我们待执行的任务,从而实现了同一时间内只有5个线程在工作。
          演示结果:
Java代码   收藏代码
  1. 仓库空了  
  2. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  3. Thread-0 消费了产品(产品ID:090505105 产品名称:电话)  
  4. 仓库空了  
  5. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  6. Thread-0 消费了产品(产品ID:090505105 产品名称:电话)  
  7. 仓库空了  
  8. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  9. Thread-2 消费了产品(产品ID:090505105 产品名称:电话)  
  10. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  11. Thread-2 消费了产品(产品ID:090505105 产品名称:电话)  
  12. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  13. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  14. Thread-2 消费了产品(产品ID:090505105 产品名称:电话)  
  15. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  16. Thread-2 消费了产品(产品ID:090505105 产品名称:电话)  
  17. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  18. Thread-2 消费了产品(产品ID:090505105 产品名称:电话)  
  19. Thread-2 生产了产品(产品ID:090505105 产品名称:电话)  
  20. Thread-0 消费了产品(产品ID:090505105 产品名称:电话)  
  21. Thread-3 消费了产品(产品ID:090505105 产品名称:电话)  
  22. Thread-1 生产了产品(产品ID:090505105 产品名称:电话)  
  23. Thread-4 消费了产品(产品ID:090505105 产品名称:电话)  

线程池负责管理工作线程,包含一个等待执行的任务队列。线程池的任务队列是一个Runnable集合,工作线程负责从任务队列中取出并执行Runnable对象。

java.util.concurrent.executors 提供了 java.util.concurrent.executor 接口的一个Java实现,可以创建线程池。下面是一个简单示例:

首先创建一个Runable 类:

WorkerThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.journaldev.threadpool;
 
public class WorkerThread implements Runnable {
 
     private String command;
 
     public WorkerThread(String s){
         this .command=s;
     }
 
     @Override
     public void run() {
         System.out.println(Thread.currentThread().getName()+ " Start. Command = " +command);
         processCommand();
         System.out.println(Thread.currentThread().getName()+ " End." );
     }
 
     private void processCommand() {
         try {
             Thread.sleep( 5000 );
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
 
     @Override
     public String toString(){
         return this .command;
     }
}

下面是一个测试程序,从 Executors 框架中创建固定大小的线程池:

SimpleThreadPool.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.journaldev.threadpool;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class SimpleThreadPool {
 
     public static void main(String[] args) {
         ExecutorService executor = Executors.newFixedThreadPool( 5 );
         for ( int i = 0 ; i < 10 ; i++) {
             Runnable worker = new WorkerThread( "" + i);
             executor.execute(worker);
           }
         executor.shutdown();
         while (!executor.isTerminated()) {
         }
         System.out.println( "Finished all threads" );
     }
 
}

在上面的程序中,我们创建了包含5个工作线程的固定大小线程池。然后,我们向线程池提交10个任务。由于线程池的大小是5,因此首先会启动5个工作线程,其他任务将进行等待。一旦有任务结束,工作线程会从等待队列中挑选下一个任务并开始执行。

以上程序的输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
pool- 1 -thread- 2 Start. Command = 1
pool- 1 -thread- 4 Start. Command = 3
pool- 1 -thread- 1 Start. Command = 0
pool- 1 -thread- 3 Start. Command = 2
pool- 1 -thread- 5 Start. Command = 4
pool- 1 -thread- 4 End.
pool- 1 -thread- 5 End.
pool- 1 -thread- 1 End.
pool- 1 -thread- 3 End.
pool- 1 -thread- 3 Start. Command = 8
pool- 1 -thread- 2 End.
pool- 1 -thread- 2 Start. Command = 9
pool- 1 -thread- 1 Start. Command = 7
pool- 1 -thread- 5 Start. Command = 6
pool- 1 -thread- 4 Start. Command = 5
pool- 1 -thread- 2 End.
pool- 1 -thread- 4 End.
pool- 1 -thread- 3 End.
pool- 1 -thread- 5 End.
pool- 1 -thread- 1 End.
Finished all threads

从输出结果看,线程池中有五个名为“pool-1-thread-1”…“pool-1-thread-5”的工作线程负责执行提交的任务。

Executors 类使用 ExecutorService  提供了一个 ThreadPoolExecutor 的简单实现,但 ThreadPoolExecutor 提供的功能远不止这些。我们可以指定创建 ThreadPoolExecutor 实例时活跃的线程数,并且可以限制线程池的大小,还可以创建自己的 RejectedExecutionHandler 实现来处理不适合放在工作队列里的任务。

下面是一个 RejectedExecutionHandler 接口的自定义实现:

RejectedExecutionHandlerImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.journaldev.threadpool;
 
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
 
public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
 
     @Override
     public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
         System.out.println(r.toString() + " is rejected" );
     }
 
}

ThreadPoolExecutor 提供了一些方法,可以查看执行状态、线程池大小、活动线程数和任务数。所以,我通过一个监视线程在固定间隔输出执行信息。

MyMonitorThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.journaldev.threadpool;
 
import java.util.concurrent.ThreadPoolExecutor;
 
public class MyMonitorThread implements Runnable
{
     private ThreadPoolExecutor executor;
 
     private int seconds;
 
     private boolean run= true ;
 
     public MyMonitorThread(ThreadPoolExecutor executor, int delay)
     {
         this .executor = executor;
         this .seconds=delay;
     }
 
     public void shutdown(){
         this .run= false ;
     }
 
     @Override
     public void run()
     {
         while (run){
                 System.out.println(
                     String.format( "[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s" ,
                         this .executor.getPoolSize(),
                         this .executor.getCorePoolSize(),
                         this .executor.getActiveCount(),
                         this .executor.getCompletedTaskCount(),
                         this .executor.getTaskCount(),
                         this .executor.isShutdown(),
                         this .executor.isTerminated()));
                 try {
                     Thread.sleep(seconds* 1000 );
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
         }
 
     }
}

下面是使用 ThreadPoolExecutor 的线程池实现示例:

WorkerPool.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.journaldev.threadpool;
 
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
public class WorkerPool {
 
     public static void main(String args[]) throws InterruptedException{
         //RejectedExecutionHandler implementation
         RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();
         //Get the ThreadFactory implementation to use
         ThreadFactory threadFactory = Executors.defaultThreadFactory();
         //creating the ThreadPoolExecutor
         ThreadPoolExecutor executorPool = new ThreadPoolExecutor( 2 , 4 , 10 , TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>( 2 ), threadFactory, rejectionHandler);
         //start the monitoring thread
         MyMonitorThread monitor = new MyMonitorThread(executorPool, 3 );
         Thread monitorThread = new Thread(monitor);
         monitorThread.start();
         //submit work to the thread pool
         for ( int i= 0 ; i< 10 ; i++){
             executorPool.execute( new WorkerThread( "cmd" +i));
         }
 
         Thread.sleep( 30000 );
         //shut down the pool
         executorPool.shutdown();
         //shut down the monitor thread
         Thread.sleep( 5000 );
         monitor.shutdown();
 
     }
}

请注意:在初始化 ThreadPoolExecutor 时,初始线程池大小设为2、最大值设为4、工作队列大小设为2。所以,如果当前有4个任务正在运行而此时又有新任务提交,工作队列将只存储2个任务和其他任务将交由RejectedExecutionHandlerImpl 处理。

程序执行的结果如下,确认了上面的结论:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
pool-1-thread-1 Start. Command = cmd0
pool-1-thread-4 Start. Command = cmd5
cmd6 is rejected
pool-1-thread-3 Start. Command = cmd4
pool-1-thread-2 Start. Command = cmd1
cmd7 is rejected
cmd8 is rejected
cmd9 is rejected
[monitor] [0 /2 ] Active: 4, Completed: 0, Task: 6, isShutdown: false , isTerminated: false
[monitor] [4 /2 ] Active: 4, Completed: 0, Task: 6, isShutdown: false , isTerminated: false
pool-1-thread-4 End.
pool-1-thread-1 End.
pool-1-thread-2 End.
pool-1-thread-3 End.
pool-1-thread-1 Start. Command = cmd3
pool-1-thread-4 Start. Command = cmd2
[monitor] [4 /2 ] Active: 2, Completed: 4, Task: 6, isShutdown: false , isTerminated: false
[monitor] [4 /2 ] Active: 2, Completed: 4, Task: 6, isShutdown: false , isTerminated: false
pool-1-thread-1 End.
pool-1-thread-4 End.
[monitor] [4 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: false , isTerminated: false
[monitor] [2 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: false , isTerminated: false
[monitor] [2 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: false , isTerminated: false
[monitor] [2 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: false , isTerminated: false
[monitor] [2 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: false , isTerminated: false
[monitor] [2 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: false , isTerminated: false
[monitor] [0 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: true , isTerminated: true
[monitor] [0 /2 ] Active: 0, Completed: 6, Task: 6, isShutdown: true , isTerminated: true

请注意活跃线程、已完成线程和任务完成总数的变化。我们可以调用 shutdown() 结束所有已提交任务并终止线程池。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池是一种用于管理和复用线程的机制,它可以提高多线程应用程序的性能和效率。线程池中的线程可以被重复使用,避免了频繁创建和销毁线程的开销。 在Java中,线程池可以通过`ExecutorService`接口来创建和管理。线程池中的线程可以执行提交给它的任务,并且可以根据需要自动创建新的线程或销毁闲置的线程。 嵌套线程池是指在一个线程池中创建另一个线程池。这种情况通常发生在需要处理一些复杂的任务,其中每个任务本身也需要使用线程池来执行。 下面是一个示例代码,演示了如何在Java中嵌套使用线程池: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class NestedThreadPoolExample { public static void main(String[] args) { // 创建外层线程池 ExecutorService outerThreadPool = Executors.newFixedThreadPool(5); // 提交任务给外层线程池 outerThreadPool.execute(() -> { // 创建内层线程池 ExecutorService innerThreadPool = Executors.newFixedThreadPool(3); // 提交任务给内层线程池 innerThreadPool.execute(() -> { // 内层线程池执行的任务 System.out.println("Inner thread pool task executed"); }); // 关闭内层线程池 innerThreadPool.shutdown(); }); // 关闭外层线程池 outerThreadPool.shutdown(); } } ``` 在上面的示例中,我们首先创建了一个外层线程池`outerThreadPool`,它使用`Executors.newFixedThreadPool()`方法创建了一个固定大小的线程池。然后,我们向外层线程池提交了一个任务,该任务在执行时创建了一个内层线程池`innerThreadPool`,并向内层线程池提交了一个任务。最后,我们分别关闭了内层线程池和外层线程池

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值