自己实现的:
线程池类:
package com.zf.threadpool; import java.util.Collections; import java.util.LinkedList; import java.util.List; public class ThreadPool { private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<Runnable>()); //任务队列 private WorkThread[] workThread ; public ThreadPool(int threadSize){ workThread = new WorkThread[threadSize]; for (int i = 0; i < workThread.length; i++) { workThread[i] = new WorkThread(i + 1); workThread[i].start(); } } public void addTask(Runnable task){ synchronized (tasks) { tasks.add(task); tasks.notifyAll(); } } public void distory(){ for (int i = 0; i < workThread.length ; i++) { workThread[i].stopThread(); } } public void openThread(){ for (int i = 0; i < workThread.length ; i++) { workThread[i].openThread(); } } private class WorkThread extends Thread { private int id ; private Runnable task ; private boolean isRuning = true; public WorkThread(int id){ this.id = id ; } public void stopThread(){ isRuning = false ; } public void openThread(){ isRuning = true ; } @Override public void run() { System.out.println("线程" + id + "初始化..."); while(isRuning){ synchronized (tasks) { while(tasks.isEmpty()){ try { tasks.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if(isRuning) task = tasks.remove(0); } System.out.println("线程" + id + "开始执行任务..."); if(task != null) task.run(); System.out.println("线程" + id + "任务执行完成..."); } } } }
测试类:
package com.zf.threadpool; public class MainTest { public static void main(String[] args) { ThreadPool tp = new ThreadPool(5); final OBJ obj = new OBJ(); for(int j = 0 ; j < 100 ; j++) { tp.addTask(new Runnable() { public void run() { for (int i = 0; i < 5 ; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); if(j == 3) tp.distory(); obj.i = obj.i++; } } } class OBJ { public int i = 0 ; }
使用java线程池: 转载http://www.bjwilly.com/archives/270.html
1.对象池的概念
Java对象的生命周期大致包括三个阶段:对象的创建,对象的使用,对象的清除。因此,对象的生命周期长度可用如下的表达式表示:T = T1 + T2 +T3。其中T1表示对象的创建时间,T2表示对象的使用时间,而T3则表示其清除时间。其中只有T2是真正有效的时间,而T1、T3则是对象本身的开销。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的时间,特别是一些很耗资源的对象创建和销毁。
2.一种简单的服务器模式
构建服务器应用的一个简单的模式:当用户请求服务器,就为用户创建一条线程,然后再新线程中进行处理。这种方法固然简单,但是有个致命缺点就是为每个请求创建一个新线程的开销很大;为每个请求创建新线程的服务器在创建和销毁线程上花费的时间和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。
3.为什么要选用线程池
线程池的重要的特性就是最大程度利用线程,减少创建和销毁线程的次数,线程池中的每个工作线程都可以被重复利用,可执行多个任务。
4.Java6中提供的线程池
A. public static ExecutorService newCachedThreadPool()
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。
B. public static ExecutorService newFixedThreadPool ()
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。
C. public static ExecutorService newSingleThreadExecutor ()
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。
可用于监听进入套接字的的连接
下面是三种线程池的示例
任务Task,模拟火箭发射倒计时
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package
com.bjwilly.thread;
public
class
LiftOff
implements
Runnable {
private
static
int
taskCount =
0
;
protected
int
countDown =
10
;
// default
private
final
int
id = taskCount++;
public
LiftOff() {
}
public
LiftOff(
int
countDown) {
this
.countDown = countDown;
}
public
String status() {
return
"#"
+ id +
"("
+ (countDown >
0
? countDown :
"Liftoff!"
)
+
"), "
;
}
@Override
public
void
run() {
while
(countDown-- >
0
) {
System.out.print(status());
Thread.yield();
}
}
}
|
newCachedThreadPool()示例
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
package
com.bjwilly.thread;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
public
class
CachedThread {
public
static
void
main(String[] args)
throws
InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
for
(
int
i =
0
; i <
5
; i++)
exec.execute(
new
LiftOff());
exec.shutdown();
}
}
|
输出结果:可以看出,任务的完成完全是没有规律的。
#0(9), #4(9), #0(8), #4(8), #0(7), #4(7), #0(6), #4(6), #0(5), #4(5), #0(4), #4(4), #0(3), #4(3), #0(2), #4(2), #0(1), #4(1), #0(Liftoff!), #4(Liftoff!), #1(9), #1(8), #1(7), #1(6), #1(5), #1(4),#1(3), #1(2), #1(1), #1(Liftoff!), #2(9), #2(8), #2(7), #2(6), #2(5), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #3(9), #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!),
newFixedThreadPool()示例
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
package
com.bjwilly.thread;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
public
class
FixedThread {
public
static
void
main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(
3
);
for
(
int
i =
0
; i <
5
; i++)
exec.execute(
new
LiftOff());
exec.shutdown();
}
}
|
输出结果:由于我创建了一个大小只有3的线程池,而实际的任务却有5个,因此过多的任务会在队列中等待直到前面的线程完成或者挂起。输出结果中先完成了0,1,2中一个任务之后才会执行随机调用3,4任务。这一切都是JVM控制的。
#0(9), #2(9), #1(9), #2(8), #0(8), #2(7), #1(8), #2(6), #1(7), #0(7), #1(6), #2(5), #1(5), #0(6), #1(4), #0(5), #0(4), #0(3), #0(2), #0(1), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #0(Liftoff!), #3(9), #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!), #4(9), #4(8), #4(7), #4(6), #4(5), #4(4), #4(3), #4(2), #4(1), #4(Liftoff!), #1(3), #1(2), #1(1), #1(Liftoff!),
newSingleThreadExecutor()示例
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
package
com.bjwilly.thread;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
public
class
SingleThread {
public
static
void
main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for
(
int
i =
0
; i <
5
; i++)
exec.execute(
new
LiftOff());
exec.shutdown();
}
}
|
输出结果:可以看出所有的任务都是按顺序来执行的。因为线程池大小只有1,多于一个都会在队列中按序等待。
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), #1(9), #1(8), #1(7), #1(6), #1(5), #1(4), #1(3), #1(2), #1(1), #1(Liftoff!), #2(9), #2(8), #2(7), #2(6), #2(5), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #3(9), #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!), #4(9), #4(8), #4(7), #4(6), #4(5), #4(4), #4(3), #4(2), #4(1), #4(Liftoff!),