`
sw1982
  • 浏览: 511336 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

ExecutorService,也不是想象中的神

阅读更多

 

关于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(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

 

2.分析里面的shutdownNow()实现,发现居然是用的thread.interrupt()。

 

    public List<Runnable> shutdownNow() {
        /*
         * shutdownNow differs from shutdown only in that
         * 1. runState is set to STOP,
         * 2. all worker threads are interrupted, not just the idle ones, and
         * 3. the queue is drained and returned.
         */
	SecurityManager security = System.getSecurityManager();
	if (security != null)
            security.checkPermission(shutdownPerm);

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (security != null) { // Check if caller can modify our threads
                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) { // Try to back out
                runState = state;
                // tryTerminate() here would be a no-op
                throw se;
            }

            List<Runnable> tasks = drainQueue();
            tryTerminate(); // Terminate now if pool and queue empty
            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. 

 

 

 

 4.恰不碰巧,我放进去的thread本身就会有很多sleep()操作,

 

sleep会在本线程被interrupt的时候抛异常,

 

    /**	
     * Causes the currently executing thread to sleep (temporarily cease 
     * execution) for the specified number of milliseconds, subject to 
     * the precision and accuracy of system timers and schedulers. The thread 
     * does not lose ownership of any monitors.
     *
     * @param      millis   the length of time to sleep in milliseconds.
     * @exception  InterruptedException if any thread has interrupted
     *             the current thread.  The <i>interrupted status</i> of the
     *             current thread is cleared when this exception is thrown.
     * @see        Object#notify()
     */
    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)	{
					//do your business
					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();
		}
//		ExecutorService pool = Executors.newFixedThreadPool(rec_thread_count);
//		pool.execute(new MsgQReceiver());
	}
 

	/**
	 * 终止消息接收线程组
	 */
	public static void stopReceiver() {
		
		if(group.size()>0) {
			for(MsgQReceiver rec : group) {
				rec.runflag = false;
			}
		}
		
		group = null;
       }
 
分享到:
评论
9 楼 sw1982 2010-04-02  
呵呵,敢问高见啊? 仔细解答一下把。
dennis_zane 写道
先学学怎么处理中断异常吧。

8 楼 dennis_zane 2010-04-02  
先学学怎么处理中断异常吧。
7 楼 zoutm 2010-04-02  
你的方法不完全对,如果是生产消费模型,最佳的终止线程的办法是生成端放入一个所谓的毒药元素,当消费者读到毒药元素,自动从线程中退出,这是最优雅的线程中断模型。
executerService.shutdown会调用中断让线程退出,因此在处理任务的时候一定要恰当处理interrupt,否则线程也退不出来。
6 楼 sw1982 2010-04-01  
无论如何,上面那个ExecutorService 关闭我的线程确实会抛出interrupt,捕获之后Executor是无法正常关闭的。

后来我改为控制runflag,而不是依赖ExecutorService
5 楼 wantofly_gj 2010-04-01  
我觉得是楼主对java线程的interrupt 以及 ExecutorService 中task 的cancel机制理解的不是很正确.强烈推荐看一下Java Concurrency.in.Practice 这本书的第7章.
4 楼 BigBlue 2010-04-01  
无论用什么,你的thread里本来就要捕捉interrupt异常,这没有什么大惊小怪的。要用好Thread,先研究好interrupt。
3 楼 JE帐号 2010-04-01  
很多人都对InterruptedException 有误解.
更准确的说是对如何停止一个线程有误解.
企图通过调用一个类似stop语义的方法停止或者杀死一个线程的想法从设计上就是错误的.线程的合理中止本质上就是个很复杂的事情,想通过外部代码直接杀死一个线程,直接的结果就是导致资源的泄漏,事务的不完整或者业务的缺失,如果从语言级别支持这种特性,带来的一定是无穷无尽的后患.你把一系列动作交给一个线程,但是又不想去规划它,而是想通过一个stop随性的想停就停本身就是个不负责的想法.

2 楼 mercyblitz 2010-03-31  
加一个isInterrupted判断就完了,既然thread被interrupted掉了,那么就不应该用sleep啦。

runflag的变量也应该跟着变化。
1 楼 qingzuochen 2010-03-31  
喜欢楼主的头像,是不是非诚勿扰里那个波妹?
代码再慢慢看,先顶上

相关推荐

    在spring boot中使用java线程池ExecutorService的讲解

    在 Spring Boot 中使用 Java 线程池 ExecutorService 的讲解 Spring Boot 作为一个流行的 Java 框架,提供了许多便捷的功能来帮助开发者快速构建应用程序。其中之一就是使用 Java 线程池 ExecutorService 来管理...

    ExecutorService方法案例文件.zip

    ExecutorService方法案例文件.zip

    ExecutorService与CompletionService对比详解.docx

    ExecutorService 和 CompletionService 是Java并发处理中的两种工具,它们用于管理和执行多个任务。ExecutorService 是一个接口,它是java.util.concurrent.Executor 接口的扩展,提供了一组方法来管理和控制线程池...

    ExecutorService用法详解.doc

    接口 java.util.concurrent.ExecutorService 表述了异步执行的机制,并且可以让任务在后台执行。壹個 ExecutorService 实例因此特别像壹個线程池。事实上,在 java.util.concurrent 包中的 ExecutorService 的实现...

    ExecutorService线程池

    ExecutorService线程池是Java并发编程中的核心组件,它位于`java.util.concurrent`包下,是`java.util.concurrent.Executor`接口的一个实现。ExecutorService提供了一种管理线程的方式,允许我们创建、管理和控制...

    ExecutorService的execute和submit方法

    在Java多线程编程中,`ExecutorService`是线程池的核心接口,它提供了一种管理线程的方式,包括创建线程、调度线程执行以及控制线程的生命周期。`ExecutorService`通过`execute()`和`submit()`这两个方法来提交任务...

    Executor,Executors,ExecutorService比较.docx

    在Java并发编程中,`Executor`、`Executors`和`ExecutorService`是核心组件,它们帮助开发者高效管理线程资源,提高程序的并发性能。理解这三个概念的区别和用途是编写高性能并发程序的关键。 1. **Executor** `...

    ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭

    总结一下,`ExecutorService.shutdown()`方法的正确理解是它会在等待所有正在执行的任务完成后再关闭线程池,而不是立即停止所有活动。这与`shutdownNow()`方法形成对比,后者试图立即停止正在执行的任务。了解这些...

    java ExecutorService使用方法详解

    Java中的`ExecutorService`是Java并发编程的重要组成部分,它提供了线程池的管理,使得开发者可以更有效地控制并发任务的执行。在Java的`java.util.concurrent`包中,`ExecutorService`接口作为线程池的核心接口,...

    运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接JAVA语言

    运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接

    详解JDK中ExecutorService与Callable和Future对线程的支持

    ExecutorService可以创建固定大小的线程池,也可以创建缓存线程池、调度线程池等。 在上面的代码中,我们使用了Executors.newFixedThreadPool方法创建了一个固定大小的线程池,大小为4。然后,我们提交了四个Task1...

    java线程池工具--ExecutorService,简单例子

    NULL 博文链接:https://x125858805.iteye.com/blog/2191873

    详解Java利用ExecutorService实现同步执行大量线程

    Java中的ExecutorService是Java并发编程的重要组成部分,它提供了一种高效、灵活的方式来管理和控制线程的...同时,合理地关闭ExecutorService(通过`shutdown()`或`shutdownNow()`方法)也是防止资源泄漏的关键步骤。

    java中Executor,ExecutorService,ThreadPoolExecutor详解

    主要介绍了java中Executor,ExecutorService,ThreadPoolExecutor详解的相关资料,需要的朋友可以参考下

    2_ExecutorService源码阅读1

    ExecutorService 是 Java 中用于管理和控制线程执行的核心接口,它是 java.util.concurrent 包的一部分。ExecutorService 扩展了 Executor 接口,提供了更丰富的功能,如任务的提交、关闭服务、检查服务状态等。这个...

    2011.08.30(2)——— java BlockingQueue ExecutorService

    标题 "2011.08.30(2)——— java BlockingQueue ExecutorService" 涉及到Java并发编程中的两个核心组件:BlockingQueue(阻塞队列)和ExecutorService。这篇博客可能深入探讨了如何使用这两个工具来优化多线程环境...

    Java 线程池ExecutorService详解及实例代码

    Java线程池ExecutorService是Java并发编程中非常重要的一个组件,它通过管理和复用线程资源,有效地控制并发任务的执行,从而提高系统的性能和稳定性。本文将详细讲解ExecutorService的原理、使用场景以及如何通过...

    Java使用ExecutorService来停止线程服务

    Java 使用 ExecutorService 来停止线程服务 Java 中的 ExecutorService 是一个非常强大...同时,我们也可以继承 AbstractExecutorService 类来自定义一个 ExecutorService,以获取开始执行但是还没有执行完毕的任务。

    java并发编程:Executor、Executors、ExecutorService.docx

    Java并发编程中的Executor、Executors和ExecutorService是Java并发编程框架的重要组成部分,它们为开发者提供了高效管理和控制线程执行的工具。以下是对这些概念的详细解释: 1. Executor: Executor是一个接口,它...

    运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接.doc

    在Java编程中,`ExecutorService`是Java并发包(`java.util.concurrent`)中的核心接口,它提供了一种管理和控制线程的方式。在处理Socket连接时,尤其是TCP和UDP通信,`ExecutorService`可以帮助我们有效地利用系统...

Global site tag (gtag.js) - Google Analytics