JobHu
随笔 - 8, 文章 - 0, 评论 - 6, 引用 - 0
数据加载中……
一个简化的java线程池示例
//以前写在blogger上的一篇老文了
曾经很好奇线程池是怎么实现的,.net中有现成的线程池可以使用,但是java中没有。还有就是Servlet的service方法是怎么样为每一个 Request在不同的线程中独立服务的,由于Servlet接口没有继承自Runnable接口,因此无法直接由一个Servlet对象生成多个线程。后来在网上找到了一个java版本的线程池的例子(http://www.informit.com/articles/article.asp?p= 30483&seqNum=1&rl=1)在该例子的基础上简化得到了下面这个版本的java线程池,记录在这里。
*******************
ThreadPool.java
*******************
package
threadPool;
import
java.util.ArrayList;
import
java.util.Collection;
public
class
ThreadPool
{
Thread[] threadArray;
Collection
<
Runnable
>
jobs
=
new
ArrayList
<
Runnable
>
();
public
ThreadPool(
int
threadNum)
{
threadArray
=
new
WorkerThread[threadNum];
for
(Thread thread : threadArray)
{
thread
=
new
WorkerThread();
thread.start();
}
}
public
synchronized
void
addJob(Runnable job)
{
jobs.add(job);
notify();
}
private
synchronized
Runnable getJob()
{
while
(jobs.isEmpty())
{
try
{
wait();
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
Runnable job
=
jobs.iterator().next();
jobs.remove(job);
return
job;
}
private
class
WorkerThread
extends
Thread
{
public
void
run()
{
Runnable job
=
null
;
while
(job
==
null
)
{
job
=
getJob();
if
(job
!=
null
)
{
job.run();
}
job
=
null
;
}
}
}
}
*******************
ThreadPoolTest.java
*******************
package
threadPool;
public
class
ThreadTest
{
private
static
class
PrintClass
implements
Runnable
{
private
int
threadNo;
public
PrintClass(
int
threadNo)
{
this
.threadNo
=
threadNo;
}
public
void
run()
{
for
(
int
i
=
0
; i
<
10
; i
++
)
{
synchronized
(System.out)
{
System.out.println(
"
Thread
"
+
threadNo
+
"
:
"
+
i);
}
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public
static
void
main(String[] args)
{
ThreadPool tp
=
new
ThreadPool(
3
);
for
(
int
i
=
0
; i
<
10
; i
++
)
{
tp.addJob(
new
PrintClass(i));
}
synchronized
(System.out)
{
System.out.println(
"
Job adding finished
"
);
}
}
}
posted on 2007-05-15 12:53
Job Hu
阅读(898)
评论(3)
编辑
收藏
评论
#
re: 一个简化的java线程池示例
回复
更多评论
DB连接池示例:
1
/**/
/*
2
* Copyright (c) 1998 by Gefion software.
3
*
4
* Permission to use, copy, and distribute this software for
5
* NON-COMMERCIAL purposes and without fee is hereby granted
6
* provided that this copyright notice appears in all copies.
7
*
8
*/
9
10
import
java.io.
*
;
11
import
java.sql.
*
;
12
import
java.util.
*
;
13
import
java.util.Date;
14
15
/** */
/**
16
* This class is a Singleton that provides access to one or many
17
* connection pools defined in a Property file. A client gets
18
* access to the single instance through the static getInstance()
19
* method and can then check-out and check-in connections from a pool.
20
* When the client shuts down it should call the release() method
21
* to close all open connections and do other clean up.
22
*/
23
public
class
DBConnectionManager
{
24
static
private
DBConnectionManager instance;
//
The single instance
25
static
private
int
clients;
26
27
private
Vector drivers
=
new
Vector();
28
private
PrintWriter log;
29
private
Hashtable pools
=
new
Hashtable();
30
31
/** */
/**
32
* Returns the single instance, creating one if it's the
33
* first time this method is called.
34
*
35
*
@return
DBConnectionManager The single instance.
36
*/
37
static
synchronized
public
DBConnectionManager getInstance()
{
38
if
(instance
==
null
)
{
39
instance
=
new
DBConnectionManager();
40
}
41
clients
++
;
42
return
instance;
43
}
44
45
/** */
/**
46
* A private constructor since this is a Singleton
47
*/
48
private
DBConnectionManager()
{
49
init();
50
}
51
52
/** */
/**
53
* Returns a connection to the named pool.
54
*
55
*
@param
name The pool name as defined in the properties file
56
*
@param
con The Connection
57
*/
58
public
void
freeConnection(String name, Connection con)
{
59
DBConnectionPool pool
=
(DBConnectionPool) pools.get(name);
60
if
(pool
!=
null
)
{
61
pool.freeConnection(con);
62
}
63
}
64
65
/** */
/**
66
* Returns an open connection. If no one is available, and the max
67
* number of connections has not been reached, a new connection is
68
* created.
69
*
70
*
@param
name The pool name as defined in the properties file
71
*
@return
Connection The connection or null
72
*/
73
public
Connection getConnection(String name)
{
74
DBConnectionPool pool
=
(DBConnectionPool) pools.get(name);
75
if
(pool
!=
null
)
{
76
return
pool.getConnection();
77
}
78
return
null
;
79
}
80
81
/** */
/**
82
* Returns an open connection. If no one is available, and the max
83
* number of connections has not been reached, a new connection is
84
* created. If the max number has been reached, waits until one
85
* is available or the specified time has elapsed.
86
*
87
*
@param
name The pool name as defined in the properties file
88
*
@param
time The number of milliseconds to wait
89
*
@return
Connection The connection or null
90
*/
91
public
Connection getConnection(String name,
long
time)
{
92
DBConnectionPool pool
=
(DBConnectionPool) pools.get(name);
93
if
(pool
!=
null
)
{
94
return
pool.getConnection(time);
95
}
96
return
null
;
97
}
98
99
/** */
/**
100
* Closes all open connections and deregisters all drivers.
101
*/
102
public
synchronized
void
release()
{
103
//
Wait until called by the last client
104
if
(
--
clients
!=
0
)
{
105
return
;
106
}
107
108
Enumeration allPools
=
pools.elements();
109
while
(allPools.hasMoreElements())
{
110
DBConnectionPool pool
=
(DBConnectionPool) allPools.nextElement();
111
pool.release();
112
}
113
Enumeration allDrivers
=
drivers.elements();
114
while
(allDrivers.hasMoreElements())
{
115
Driver driver
=
(Driver) allDrivers.nextElement();
116
try
{
117
DriverManager.deregisterDriver(driver);
118
log(
"
Deregistered JDBC driver
"
+
driver.getClass().getName());
119
}
120
catch
(SQLException e)
{
121
log(e,
"
Can't deregister JDBC driver:
"
+
driver.getClass().getName());
122
}
123
}
124
}
125
126
/** */
/**
127
* Creates instances of DBConnectionPool based on the properties.
128
* A DBConnectionPool can be defined with the following properties:
129
* <PRE>
130
* <poolname>.url The JDBC URL for the database
131
* <poolname>.user A database user (optional)
132
* <poolname>.password A database user password (if user specified)
133
* <poolname>.maxconn The maximal number of connections (optional)
134
* </PRE>
135
*
136
*
@param
props The connection pool properties
137
*/
138
private
void
createPools(Properties props)
{
139
Enumeration propNames
=
props.propertyNames();
140
while
(propNames.hasMoreElements())
{
141
String name
=
(String) propNames.nextElement();
142
if
(name.endsWith(
"
.url
"
))
{
143
String poolName
=
name.substring(
0
, name.lastIndexOf(
"
.
"
));
144
String url
=
props.getProperty(poolName
+
"
.url
"
);
145
if
(url
==
null
)
{
146
log(
"
No URL specified for
"
+
poolName);
147
continue
;
148
}
149
String user
=
props.getProperty(poolName
+
"
.user
"
);
150
String password
=
props.getProperty(poolName
+
"
.password
"
);
151
String maxconn
=
props.getProperty(poolName
+
"
.maxconn
"
,
"
0
"
);
152
int
max;
153
try
{
154
max
=
Integer.valueOf(maxconn).intValue();
155
}
156
catch
(NumberFormatException e)
{
157
log(
"
Invalid maxconn value
"
+
maxconn
+
"
for
"
+
poolName);
158
max
=
0
;
159
}
160
DBConnectionPool pool
=
161
new
DBConnectionPool(poolName, url, user, password, max);
162
pools.put(poolName, pool);
163
log(
"
Initialized pool
"
+
poolName);
164
}
165
}
166
}
167
168
/** */
/**
169
* Loads properties and initializes the instance with its values.
170
*/
171
private
void
init()
{
172
InputStream is
=
getClass().getResourceAsStream(
"
/db.properties
"
);
173
Properties dbProps
=
new
Properties();
174
try
{
175
dbProps.load(is);
176
}
177
catch
(Exception e)
{
178
System.err.println(
"
Can't read the properties file.
"
+
179
"
Make sure db.properties is in the CLASSPATH
"
);
180
return
;
181
}
182
String logFile
=
dbProps.getProperty(
"
logfile
"
,
"
DBConnectionManager.log
"
);
183
try
{
184
log
=
new
PrintWriter(
new
FileWriter(logFile,
true
),
true
);
185
}
186
catch
(IOException e)
{
187
System.err.println(
"
Can't open the log file:
"
+
logFile);
188
log
=
new
PrintWriter(System.err);
189
}
190
loadDrivers(dbProps);
191
createPools(dbProps);
192
}
193
194
/** */
/**
195
* Loads and registers all JDBC drivers. This is done by the
196
* DBConnectionManager, as opposed to the DBConnectionPool,
197
* since many pools may share the same driver.
198
*
199
*
@param
props The connection pool properties
200
*/
201
private
void
loadDrivers(Properties props)
{
202
String driverClasses
=
props.getProperty(
"
drivers
"
);
203
StringTokenizer st
=
new
StringTokenizer(driverClasses);
204
while
(st.hasMoreElements())
{
205
String driverClassName
=
st.nextToken().trim();
206
try
{
207
Driver driver
=
(Driver)
208
Class.forName(driverClassName).newInstance();
209
DriverManager.registerDriver(driver);
210
drivers.addElement(driver);
211
log(
"
Registered JDBC driver
"
+
driverClassName);
212
}
213
catch
(Exception e)
{
214
log(
"
Can't register JDBC driver:
"
+
215
driverClassName
+
"
, Exception:
"
+
e);
216
}
217
}
218
}
219
220
/** */
/**
221
* Writes a message to the log file.
222
*/
223
private
void
log(String msg)
{
224
log.println(
new
Date()
+
"
:
"
+
msg);
225
}
226
227
/** */
/**
228
* Writes a message with an Exception to the log file.
229
*/
230
private
void
log(Throwable e, String msg)
{
231
log.println(
new
Date()
+
"
:
"
+
msg);
232
e.printStackTrace(log);
233
}
234
235
/** */
/**
236
* This inner class represents a connection pool. It creates new
237
* connections on demand, up to a max number if specified.
238
* It also makes sure a connection is still open before it is
239
* returned to a client.
240
*/
241
class
DBConnectionPool
{
242
private
int
checkedOut;
243
private
Vector freeConnections
=
new
Vector();
244
private
int
maxConn;
245
private
String name;
246
private
String password;
247
private
String URL;
248
private
String user;
249
250
/** */
/**
251
* Creates new connection pool.
252
*
253
*
@param
name The pool name
254
*
@param
URL The JDBC URL for the database
255
*
@param
user The database user, or null
256
*
@param
password The database user password, or null
257
*
@param
maxConn The maximal number of connections, or 0
258
* for no limit
259
*/
260
public
DBConnectionPool(String name, String URL, String user, String password,
261
int
maxConn)
{
262
this
.name
=
name;
263
this
.URL
=
URL;
264
this
.user
=
user;
265
this
.password
=
password;
266
this
.maxConn
=
maxConn;
267
}
268
269
/** */
/**
270
* Checks in a connection to the pool. Notify other Threads that
271
* may be waiting for a connection.
272
*
273
*
@param
con The connection to check in
274
*/
275
public
synchronized
void
freeConnection(Connection con)
{
276
//
Put the connection at the end of the Vector
277
freeConnections.addElement(con);
278
checkedOut
--
;
279
notifyAll();
280
}
281
282
/** */
/**
283
* Checks out a connection from the pool. If no free connection
284
* is available, a new connection is created unless the max
285
* number of connections has been reached. If a free connection
286
* has been closed by the database, it's removed from the pool
287
* and this method is called again recursively.
288
*/
289
public
synchronized
Connection getConnection()
{
290
Connection con
=
null
;
291
if
(freeConnections.size()
>
0
)
{
292
//
Pick the first Connection in the Vector
293
//
to get round-robin usage
294
con
=
(Connection) freeConnections.firstElement();
295
freeConnections.removeElementAt(
0
);
296
try
{
297
if
(con.isClosed())
{
298
log(
"
Removed bad connection from
"
+
name);
299
//
Try again recursively
300
con
=
getConnection();
301
}
302
}
303
catch
(SQLException e)
{
304
log(
"
Removed bad connection from
"
+
name);
305
//
Try again recursively
306
con
=
getConnection();
307
}
308
}
309
else
if
(maxConn
==
0
||
checkedOut
<
maxConn)
{
310
con
=
newConnection();
311
}
312
if
(con
!=
null
)
{
313
checkedOut
++
;
314
}
315
return
con;
316
}
317
318
/** */
/**
319
* Checks out a connection from the pool. If no free connection
320
* is available, a new connection is created unless the max
321
* number of connections has been reached. If a free connection
322
* has been closed by the database, it's removed from the pool
323
* and this method is called again recursively.
324
* <P>
325
* If no connection is available and the max number has been
326
* reached, this method waits the specified time for one to be
327
* checked in.
328
*
329
*
@param
timeout The timeout value in milliseconds
330
*/
331
public
synchronized
Connection getConnection(
long
timeout)
{
332
long
startTime
=
new
Date().getTime();
333
Connection con;
334
while
((con
=
getConnection())
==
null
)
{
335
try
{
336
wait(timeout);
337
}
338
catch
(InterruptedException e)
{}
339
if
((
new
Date().getTime()
-
startTime)
>=
timeout)
{
340
//
Timeout has expired
341
return
null
;
342
}
343
}
344
return
con;
345
}
346
347
/** */
/**
348
* Closes all available connections.
349
*/
350
public
synchronized
void
release()
{
351
Enumeration allConnections
=
freeConnections.elements();
352
while
(allConnections.hasMoreElements())
{
353
Connection con
=
(Connection) allConnections.nextElement();
354
try
{
355
con.close();
356
log(
"
Closed connection for pool
"
+
name);
357
}
358
catch
(SQLException e)
{
359
log(e,
"
Can't close connection for pool
"
+
name);
360
}
361
}
362
freeConnections.removeAllElements();
363
}
364
365
/** */
/**
366
* Creates a new connection, using a userid and password
367
* if specified.
368
*/
369
private
Connection newConnection()
{
370
Connection con
=
null
;
371
try
{
372
if
(user
==
null
)
{
373
con
=
DriverManager.getConnection(URL);
374
}
375
else
{
376
con
=
DriverManager.getConnection(URL, user, password);
377
}
378
log(
"
Created a new connection in pool
"
+
name);
379
}
380
catch
(SQLException e)
{
381
log(e,
"
Can't create a new connection for
"
+
URL);
382
return
null
;
383
}
384
return
con;
385
}
386
}
387
}
2007-05-16 18:20 |
klvt
#
re: 一个简化的java线程池示例
回复
更多评论
扁担长
板凳
宽扁担想绑在
板凳
上
板凳
不让扁担绑在
板凳
上扁担偏要绑在
板凳
上
板凳
偏偏不让扁担绑在那
板凳
上
2007-05-18 16:39 |
klvt
#
re: 一个简化的java线程池示例
回复
更多评论
JDK1.5中已经提供线程池的支持了 java.util.concurrent 包
2007-06-15 15:41 |
jasson
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
Chat2DB
C++博客
博问
Powered by:
BlogJava
Copyright © Job Hu
导航
BlogJava
首页
新随笔
联系
聚合
管理
<
2007年6月
>
日
一
二
三
四
五
六
27
28
29
30
31
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
1
2
3
4
5
6
7
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(1)
给我留言
查看公开留言
查看私人留言
随笔分类
Tomcat源代码(2)
(rss)
算法与数据结构(2)
(rss)
随笔档案
2007年7月 (4)
2007年5月 (3)
2007年4月 (1)
搜索
最新评论
1. re: Java Language Keywords[未登录]
无料
--klvt
2. re: 一个简化的java线程池示例
JDK1.5中已经提供线程池的支持了 java.util.concurrent 包
--jasson
3. re: Tomcat笔记(三)
Cool~写的好!
莫非你也要写一个类似tomcat的咚咚?
--yans
4. re: 一个简化的java线程池示例
评论内容较长,点击标题查看
--klvt
5. re: 一个简化的java线程池示例
评论内容较长,点击标题查看
--klvt
阅读排行榜
1. 一个简化的java线程池示例(898)
2. 实现一个栈,使其push,pop,min(取得栈中的最小元素)均为O(1)(894)
3. 二叉排序树变为双向链表(641)
4. Tomcat笔记(三)(353)
5. Tomcat笔记(一)(342)
评论排行榜
1. 一个简化的java线程池示例(3)
2. Tomcat笔记(一)(1)
3. Java Language Keywords(1)
4. Tomcat笔记(三)(1)
5. Tomcat笔记(二)(0)