原文地址:http://www.iteye.com/topic/628507
关于ExecutorService好用的方面就不说了,effective java里面是强烈推荐使用Executor代替自己管理Thread。
e.g.
- public static void startReceiver() {
- ExecutorService pool = Executors.newFixedThreadPool(rec_thread_count);
- pool.execute(new MsgQReceiver());
- }
下面看看今天我郁闷的地方:
1.JDK doc里面描述的线程池关闭方法:先暂停接受新任务进来,然后terminate运行中的线程。看起来确实是一个非常完美的方案。
- void shutdownAndAwaitTermination(ExecutorService pool) {
- pool.shutdown();
- try {
-
- if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
- pool.shutdownNow();
-
- if (!pool.awaitTermination(60, TimeUnit.SECONDS))
- System.err.println("Pool did not terminate");
- }
- } catch (InterruptedException ie) {
-
- pool.shutdownNow();
-
- Thread.currentThread().interrupt();
- }
- }
2.分析里面的shutdownNow()实现,发现居然是用的thread.interrupt()。
- public List<Runnable> shutdownNow() {
-
-
-
-
-
-
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- security.checkPermission(shutdownPerm);
-
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
- if (security != null) {
- for (Worker w : workers)
- security.checkAccess(w.thread);
- }
-
- int state = runState;
- if (state < STOP)
- runState = STOP;
-
- try {
- for (Worker w : workers) {
- w.interruptNow();
- }
- } catch (SecurityException se) {
- runState = state;
-
- throw se;
- }
-
- List<Runnable> tasks = drainQueue();
- tryTerminate();
- return tasks;
- } finally {
- mainLock.unlock();
- }
- }
3.在jdk5之后,线程的stop()方法已经被不推荐使用,并且没有替代品。文档上如是说:
建议线程通过里面设置boolean runflag,不停轮询该变量来确定是否继续执行(具体做法可以参考下面我的demo)
- Deprecated. This method is inherently unsafe. Stopping a thread with Thread.stop causes it to
- unlock all of the monitors that it has locked 。 Many uses of stop should be replaced by code that
- simply modifies some variable to indicate that the target thread should stop running.
- The target thread should check this variable regularly, and return from its run method in an orderly
- fashion if the variable indicates that it is to stop running. If the target thread waits for long periods
- (on a condition variable, for example), the interrupt method should be used to interrupt the wait.<span style="white-space: normal;"> </span>
4.恰不碰巧,我放进去的thread本身就会有很多sleep()操作,
sleep会在本线程被interrupt的时候抛异常,
-
-
-
-
-
-
-
-
-
-
-
-
- public static native void sleep(long millis) throws InterruptedException;
interrupte方法如是说明:
If this thread is blocked in an invocation of the wait()
, wait(long)
, or wait(long, int)
methods of the Object
class, or of the join()
, join(long)
, join(long, int)
, sleep(long)
, or sleep(long, int)
, methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException
.
那么使用ExecutorService来关闭我下面这些线程,碰到可能都会是抛出InterruptedException 。走到异常流程并非
优雅的方式,也就失去了步骤1中的意义。
- while(runflag) {
-
- try {
- Thread.sleep(30);
- } catch (InterruptedException e) {
- logger.error("msg收取线程sleep异常", e);
- }
-
- } else if (stRet.iRet == -1) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- logger.error("msg收取线程sleep异常", e);
- }
- } else {
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- logger.error("msg收取线程sleep异常", e);
- }
- }
end:
于是乎,只好回归原始.自己通过改变runflag来友好的关闭线程。
- public static void startReceiver() {
-
- for(int i=0;i<rec_thread_count;i++) {
- MsgQReceiver rec = new MsgQReceiver();
- group.add(rec);
- rec.start();
- }
-
-
- }
-
-
-
- public static void stopReceiver() {
-
- if(group.size()>0) {
- for(MsgQReceiver rec : group) {
- rec.runflag = false;
- }
- }
-
- group = null;
- }