如何使用Spring开发和监控线程池服务

线程池对执行同步或异步的任务很重要。本文展示如何利用Spring开发并监控线程池服务。创建线程池的其他两种方法已讲解过。

使用技术

  • JDK 1.6.0_21
  • Spring 3.0.5
  • Maven 3.0.2

第1步:创建Maven工程

下面是一个maven工程。(可以使用Maven或IDE的插件创建)。

第2步:添加依赖库

将Spring的依赖添加到Maven的pom.xml文件中。

1
2
3
4
5
6
7
8
9
10
11
<!-- Spring 3 dependencies -->
< dependency >
     < groupId >org.springframework</ groupId >
     < artifactId >spring-core</ artifactId >
     < version >${spring.version}</ version >
</ dependency >
< dependency >
     < groupId >org.springframework</ groupId >
     < artifactId >spring-context</ artifactId >
     < version >${spring.version}</ version >
</ dependency >

使用下面的插件创建可执行jar包。

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
< plugin >
     < groupId >org.apache.maven.plugins</ groupId >
     < artifactId >maven-shade-plugin</ artifactId >
     < version >1.3.1</ version >
     < executions >
         < execution >
             < phase >package</ phase >
             < goals >
                 < goal >shade</ goal >
             </ goals >
             < configuration >
                 < transformers >
                     < transformer
                         implementation = "org.apache.maven.plugins.shade.resource.ManifestResourceTransformer" >
                         < mainClass >com.otv.exe.Application</ mainClass >
                     </ transformer >
                     < transformer
                         implementation = "org.apache.maven.plugins.shade.resource.AppendingTransformer" >
                         < resource >META-INF/spring.handlers</ resource >
                     </ transformer >
                     < transformer
                         implementation = "org.apache.maven.plugins.shade.resource.AppendingTransformer" >
                         < resource >META-INF/spring.schemas</ resource >
                     </ transformer >
                 </ transformers >
             </ configuration >
         </ execution >
     </ executions >
</ plugin >

第3步:创建任务类

创建一个实现Runnable接口的新TestTask类。这个类表示要执行的任务。

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
45
46
package com.otv.task;
 
import org.apache.log4j.Logger;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public class TestTask implements Runnable {
 
     private static Logger log = Logger.getLogger(TestTask. class );
     String taskName;
 
     public TestTask() {
     }
 
     public TestTask(String taskName) {
         this .taskName = taskName;
     }
 
     public void run() {
         try {
             log.debug( this .taskName + " : is started." );
             Thread.sleep( 10000 );
             log.debug( this .taskName + " : is completed." );
         } catch (InterruptedException e) {
             log.error( this .taskName + " : is not completed!" );
             e.printStackTrace();
         }      
     }
 
     @Override
     public String toString() {
         return (getTaskName());
     }
 
     public String getTaskName() {
         return taskName;
     }
 
     public void setTaskName(String taskName) {
         this .taskName = taskName;
     }
}

第4步:创建TestRejectedExecutionHandler类

TestRejectedExecutionHandler类实现了RejectedExecutionHandler接口。如果没有空闲线程并且队列超出限制,任务会被拒绝。这个类处理被拒绝的任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.otv.handler;
 
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
 
import org.apache.log4j.Logger;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public class TestRejectedExecutionHandler implements RejectedExecutionHandler {
 
     private static Logger log = Logger.getLogger(TestRejectedExecutionHandler. class );
 
     public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
         log.debug(runnable.toString() + " : has been rejected" );
     }
}

第5步:创建ITestThreadPoolExecutorService接口

创建ITestThreadPoolExecutorService接口。(译者注:这个接口的主要功能是通过设置的参数创建一个线程池)

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
package com.otv.srv;
 
import java.util.concurrent.ThreadPoolExecutor;
 
import com.otv.handler.TestRejectedExecutionHandler;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public interface ITestThreadPoolExecutorService {
 
     public ThreadPoolExecutor createNewThreadPool();
 
     public int getCorePoolSize();
 
     public void setCorePoolSize( int corePoolSize);
 
     public int getMaxPoolSize();
 
     public void setMaxPoolSize( int maximumPoolSize);
 
     public long getKeepAliveTime();
 
     public void setKeepAliveTime( long keepAliveTime);
 
     public int getQueueCapacity();
 
     public void setQueueCapacity( int queueCapacity);
 
     public TestRejectedExecutionHandler getTestRejectedExecutionHandler();
 
     public void setTestRejectedExecutionHandler(TestRejectedExecutionHandler testRejectedExecutionHandler);
 
}

第6步:创建TestThreadPoolExecutorService类

TestThreadPoolExecutorService类实现了ITestThreadPoolExecutorService接口(上一步创建的接口)。这个类可以创建一个新的线程池。

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.otv.srv;
 
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
import com.otv.handler.TestRejectedExecutionHandler;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public class TestThreadPoolExecutorService implements ITestThreadPoolExecutorService {
 
     private int  corePoolSize;
     private int  maxPoolSize;
     private long keepAliveTime;
     private int  queueCapacity;
     TestRejectedExecutionHandler testRejectedExecutionHandler;
 
     public ThreadPoolExecutor createNewThreadPool() {
         ThreadPoolExecutor executor = new ThreadPoolExecutor(getCorePoolSize(),
                                                                 getMaxPoolSize(),
                                                                 getKeepAliveTime(),
                                                                 TimeUnit.SECONDS,
                                                                 new ArrayBlockingQueue(getQueueCapacity()),
                                                                 getTestRejectedExecutionHandler());
         return executor;
     }
 
     public int getCorePoolSize() {
         return corePoolSize;
     }
 
     public void setCorePoolSize( int corePoolSize) {
         this .corePoolSize = corePoolSize;
     }
 
     public int getMaxPoolSize() {
         return maxPoolSize;
     }
 
     public void setMaxPoolSize( int maxPoolSize) {
         this .maxPoolSize = maxPoolSize;
     }
 
     public long getKeepAliveTime() {
         return keepAliveTime;
     }
 
     public void setKeepAliveTime( long keepAliveTime) {
         this .keepAliveTime = keepAliveTime;
     }
 
     public int getQueueCapacity() {
         return queueCapacity;
     }
 
     public void setQueueCapacity( int queueCapacity) {
         this .queueCapacity = queueCapacity;
     }
 
     public TestRejectedExecutionHandler getTestRejectedExecutionHandler() {
         return testRejectedExecutionHandler;
     }
 
     public void setTestRejectedExecutionHandler(TestRejectedExecutionHandler testRejectedExecutionHandler) {
         this .testRejectedExecutionHandler = testRejectedExecutionHandler;
     }
}

第7步: 创建IThreadPoolMonitorService接口

创建IThreadPoolMonitorService接口

1
2
3
4
5
6
7
8
9
10
11
12
package com.otv.monitor.srv;
 
import java.util.concurrent.ThreadPoolExecutor;
 
public interface IThreadPoolMonitorService extends Runnable {
 
     public void monitorThreadPool();
 
     public ThreadPoolExecutor getExecutor();
 
     public void setExecutor(ThreadPoolExecutor executor);
}

第8步:创建ThreadPoolMonitorService类

ThreadPoolMonitorService类实现了IThreadPoolMonitorService接口。这个类用来监控已创建的线程池。

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
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.otv.monitor.srv;
 
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.log4j.Logger;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public class ThreadPoolMonitorService implements IThreadPoolMonitorService {
 
     private static Logger log = Logger.getLogger(ThreadPoolMonitorService. class );
     ThreadPoolExecutor executor;
     private long monitoringPeriod;
 
     public void run() {
         try {
             while ( true ){
                 monitorThreadPool();
                 Thread.sleep(monitoringPeriod* 1000 );
             }
         } catch (Exception e) {
             log.error(e.getMessage());
         }
     }
 
     public void monitorThreadPool() {
         StringBuffer strBuff = new StringBuffer();
         strBuff.append( "CurrentPoolSize : " ).append(executor.getPoolSize());
         strBuff.append( " - CorePoolSize : " ).append(executor.getCorePoolSize());
         strBuff.append( " - MaximumPoolSize : " ).append(executor.getMaximumPoolSize());
         strBuff.append( " - ActiveTaskCount : " ).append(executor.getActiveCount());
         strBuff.append( " - CompletedTaskCount : " ).append(executor.getCompletedTaskCount());
         strBuff.append( " - TotalTaskCount : " ).append(executor.getTaskCount());
         strBuff.append( " - isTerminated : " ).append(executor.isTerminated());
 
         log.debug(strBuff.toString());
     }
 
     public ThreadPoolExecutor getExecutor() {
         return executor;
     }
 
     public void setExecutor(ThreadPoolExecutor executor) {
         this .executor = executor;
     }  
 
     public long getMonitoringPeriod() {
         return monitoringPeriod;
     }
 
     public void setMonitoringPeriod( long monitoringPeriod) {
         this .monitoringPeriod = monitoringPeriod;
     }
}

第9步:创建Starter类

(译者注:这个类内部维护了一个线程池服务(testThreadPoolExecutorService)和一个监控服务(threadPoolMonitorService),然后创建线程池、启动一个单独的线程执行监控服务、通过线程池执行任务)

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.otv.start;
 
import java.util.concurrent.ThreadPoolExecutor;
 
import org.apache.log4j.Logger;
 
import com.otv.handler.TestRejectedExecutionHandler;
import com.otv.monitor.srv.IThreadPoolMonitorService;
import com.otv.monitor.srv.ThreadPoolMonitorService;
import com.otv.srv.ITestThreadPoolExecutorService;
import com.otv.srv.TestThreadPoolExecutorService;
import com.otv.task.TestTask;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public class Starter {
 
     private static Logger log = Logger.getLogger(TestRejectedExecutionHandler. class );
 
     IThreadPoolMonitorService threadPoolMonitorService;
     ITestThreadPoolExecutorService testThreadPoolExecutorService;
 
     public void start() {
 
         // A new thread pool is created...
         ThreadPoolExecutor executor = testThreadPoolExecutorService.createNewThreadPool();
         executor.allowCoreThreadTimeOut( true );
 
         // Created executor is set to ThreadPoolMonitorService...
         threadPoolMonitorService.setExecutor(executor);
 
         // ThreadPoolMonitorService is started...
         Thread monitor = new Thread(threadPoolMonitorService);
         monitor.start();
 
         // New tasks are executed...
         for ( int i= 1 ;i&lt; 10 ;i++) {
             executor.execute( new TestTask(&quot;Task&quot;+i));
         }
 
         try {
             Thread.sleep( 40000 );
         } catch (Exception e)   {
             log.error(e.getMessage());
         }
 
         for ( int i= 10 ;i&lt; 19 ;i++) {
             executor.execute( new TestTask(&quot;Task&quot;+i));
         }
 
         // executor is shutdown...
         executor.shutdown();
     }  
 
     public IThreadPoolMonitorService getThreadPoolMonitorService() {
         return threadPoolMonitorService;
     }
 
     public void setThreadPoolMonitorService(IThreadPoolMonitorService threadPoolMonitorService) {
         this .threadPoolMonitorService = threadPoolMonitorService;
     }
 
     public ITestThreadPoolExecutorService getTestThreadPoolExecutorService() {
         return testThreadPoolExecutorService;
     }
 
     public void setTestThreadPoolExecutorService(ITestThreadPoolExecutorService testThreadPoolExecutorService) {
         this .testThreadPoolExecutorService = testThreadPoolExecutorService;
     }
}

第10步:创建Application类

创建Application类。这个类运行应用程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.otv.start;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
  * @author onlinetechvision.com
  * @since 17 Oct 2011
  * @version 1.0.0
  *
  */
public class Application {
 
     public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(&quot;applicationContext.xml&quot;);
        Starter starter = (Starter) context.getBean(&quot;Starter&quot;);
        starter.start();
     }
}
第11步:创建applicationContext.xml文件

(译者注:在Spring中注册了上面所创建的类,并提前设置了部分相应的参数,比如将监控服务的监控周期设为5)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
< beans xmlns = "http://www.springframework.org/schema/beans"
     xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
     <!-- Beans Declaration -->
     < bean id = "TestTask" class = "com.otv.task.TestTask" ></ bean >
     < bean id = "ThreadPoolMonitorService" class = "com.otv.monitor.srv.ThreadPoolMonitorService" >
         < property name = "monitoringPeriod"  value = "5" />
     </ bean >
     < bean id = "TestRejectedExecutionHandler" class = "com.otv.handler.TestRejectedExecutionHandler" ></ bean >
     < bean id = "TestThreadPoolExecutorService" class = "com.otv.srv.TestThreadPoolExecutorService" >
         < property name = "corePoolSize"  value = "1" />
         < property name = "maxPoolSize"   value = "3" />
         < property name = "keepAliveTime" value = "10" />
         < property name = "queueCapacity" value = "3" />
         < property name = "testRejectedExecutionHandler" ref = "TestRejectedExecutionHandler" />
     </ bean >
     < bean id = "Starter" class = "com.otv.start.Starter" >
         < property name = "threadPoolMonitorService" ref = "ThreadPoolMonitorService" />
         < property name = "testThreadPoolExecutorService" ref = "TestThreadPoolExecutorService" />
     </ bean >
</ beans >

第12步:创建线程池的另一方法

Spring提供的ThreadPoolTaskExecutor类也可以创建线程池。

(译者注:上面通过我们自己创建的TestThreadPoolExecutorService类来设置线程池的各项参数并创建线程池,但实际上Spring也提供了功能类似的类,就是ThreadPoolTaskExecutor。所以也可以使用这种方式创建线程池)

1
2
3
4
5
6
7
8
9
< bean id = "threadPoolTaskExecutor" class = "org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
   < property name = "corePoolSize"  value = "1" />
   < property name = "maxPoolSize"   value = "3" />
   < property name = "queueCapacity" value = "3" />
</ bean >
 
< bean id = "testTaskExecutor" class = "TestTaskExecutor" >
   < constructor-arg ref = "threadPoolTaskExecutor" />
</ bean >

第13步:构建项目

OTV_Spring_ThreadPool工程被build后,就会产生一个OTV_Spring_ThreadPool-0.0.1-SNAPSHOT.jar包。

第14步:运行工程

OTV_Spring_ThreadPool-0.0.1-SNAPSHOT.jar运行后,输出日志如下:

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
18.10 . 2011 20 : 08 : 48 DEBUG (TestRejectedExecutionHandler.java: 19 ) - Task7 : has been rejected
18.10 . 2011 20 : 08 : 48 DEBUG (TestRejectedExecutionHandler.java: 19 ) - Task8 : has been rejected
18.10 . 2011 20 : 08 : 48 DEBUG (TestRejectedExecutionHandler.java: 19 ) - Task9 : has been rejected
18.10 . 2011 20 : 08 : 48 DEBUG (TestTask.java: 25 ) - Task1 : is started.
18.10 . 2011 20 : 08 : 48 DEBUG (TestTask.java: 25 ) - Task6 : is started.
18.10 . 2011 20 : 08 : 48 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 2 - CompletedTaskCount : 0 - TotalTaskCount : 5 - isTerminated : false
18.10 . 2011 20 : 08 : 48 DEBUG (TestTask.java: 25 ) - Task5 : is started.
18.10 . 2011 20 : 08 : 53 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 0 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 08 : 58 DEBUG (TestTask.java: 27 ) - Task6 : is completed.
18.10 . 2011 20 : 08 : 58 DEBUG (TestTask.java: 27 ) - Task1 : is completed.
18.10 . 2011 20 : 08 : 58 DEBUG (TestTask.java: 25 ) - Task3 : is started.
18.10 . 2011 20 : 08 : 58 DEBUG (TestTask.java: 25 ) - Task2 : is started.
18.10 . 2011 20 : 08 : 58 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 2 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 08 : 58 DEBUG (TestTask.java: 27 ) - Task5 : is completed.
18.10 . 2011 20 : 08 : 58 DEBUG (TestTask.java: 25 ) - Task4 : is started.
18.10 . 2011 20 : 09 : 03 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 3 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 09 : 08 DEBUG (TestTask.java: 27 ) - Task2 : is completed.
18.10 . 2011 20 : 09 : 08 DEBUG (TestTask.java: 27 ) - Task3 : is completed.
18.10 . 2011 20 : 09 : 08 DEBUG (TestTask.java: 27 ) - Task4 : is completed.
18.10 . 2011 20 : 09 : 08 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 0 - CompletedTaskCount : 6 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 09 : 13 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 0 - CompletedTaskCount : 6 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 09 : 18 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 0 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 0 - CompletedTaskCount : 6 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 09 : 23 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 0 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 0 - CompletedTaskCount : 6 - TotalTaskCount : 6 - isTerminated : false
18.10 . 2011 20 : 09 : 28 DEBUG (TestTask.java: 25 ) - Task10 : is started.
18.10 . 2011 20 : 09 : 28 DEBUG (TestRejectedExecutionHandler.java: 19 ) - Task16 : has been rejected
18.10 . 2011 20 : 09 : 28 DEBUG (TestRejectedExecutionHandler.java: 19 ) - Task17 : has been rejected
18.10 . 2011 20 : 09 : 28 DEBUG (TestRejectedExecutionHandler.java: 19 ) - Task18 : has been rejected
18.10 . 2011 20 : 09 : 28 DEBUG (TestTask.java: 25 ) - Task14 : is started.
18.10 . 2011 20 : 09 : 28 DEBUG (TestTask.java: 25 ) - Task15 : is started.
18.10 . 2011 20 : 09 : 28 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 6 - TotalTaskCount : 12 - isTerminated : false
18.10 . 2011 20 : 09 : 33 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 6 - TotalTaskCount : 12 - isTerminated : false
18.10 . 2011 20 : 09 : 38 DEBUG (TestTask.java: 27 ) - Task10 : is completed.
18.10 . 2011 20 : 09 : 38 DEBUG (TestTask.java: 25 ) - Task11 : is started.
18.10 . 2011 20 : 09 : 38 DEBUG (TestTask.java: 27 ) - Task14 : is completed.
18.10 . 2011 20 : 09 : 38 DEBUG (TestTask.java: 27 ) - Task15 : is completed.
18.10 . 2011 20 : 09 : 38 DEBUG (TestTask.java: 25 ) - Task12 : is started.
18.10 . 2011 20 : 09 : 38 DEBUG (TestTask.java: 25 ) - Task13 : is started.
18.10 . 2011 20 : 09 : 38 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 9 - TotalTaskCount : 12 - isTerminated : false
18.10 . 2011 20 : 09 : 43 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 3 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 3 - CompletedTaskCount : 9 - TotalTaskCount : 12 - isTerminated : false
18.10 . 2011 20 : 09 : 48 DEBUG (TestTask.java: 27 ) - Task11 : is completed.
18.10 . 2011 20 : 09 : 48 DEBUG (TestTask.java: 27 ) - Task13 : is completed.
18.10 . 2011 20 : 09 : 48 DEBUG (TestTask.java: 27 ) - Task12 : is completed.
18.10 . 2011 20 : 09 : 48 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 0 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 0 - CompletedTaskCount : 12 - TotalTaskCount : 12 - isTerminated : true
18.10 . 2011 20 : 09 : 53 DEBUG (ThreadPoolMonitorService.java: 39 ) - CurrentPoolSize : 0 - CorePoolSize : 1 - MaximumPoolSize : 3 - ActiveTaskCount : 0 - CompletedTaskCount : 12 - TotalTaskCount : 12 - isTerminated : true

第15步:下载

原文链接: dzone 翻译: ImportNew.com - 文 学敏
译文链接: http://www.importnew.com/14163.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值