`

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

阅读更多
看到一个博客,如下
Java多线程-线程池ExecutorService.shutdown什么时候执行

其中问题:
ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭。
但是我用了计数信号量Semaphore后,发现线程还没有跑完,他就执行了shutdown().


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest extends Thread {
	Semaphore position;
	private int id;

	public SemaphoreTest(int i, Semaphore s) {
		this.id = i;
		this.position = s;
	}

	public void run() {
		try {
			if (position.availablePermits() > 0) {
				System.out.println("顾客[" + id + "]进入厕所,有空位");
			} else {
				System.out.println("顾客[" + id + "]进入厕所,没空位,排队");
			}
			position.acquire();
			System.out.println("【" + id + "】acquire坑位");
			Thread.sleep((int) (Math.random() * 1000));
			System.out.println("【" + id + "】完毕release");
			position.release();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) {
		ExecutorService pool = Executors.newCachedThreadPool();
		Semaphore position = new Semaphore(2); // 初始化两个空位
		for (int i = 0; i < 5; i++) {
			pool.submit(new SemaphoreTest(i, position));
		}
		System.out.println("开始释放线程池资源");
		pool.shutdown();
		System.out.println("完成释放线程池资源");
		position.acquireUninterruptibly(2);
		System.out.println("如厕完毕,清理厕所");
		position.release(2);
	}
}


PS:
1、代码中主线程并没有等待线程池执行完毕这一说,而是持续往下执行
2、至于信号量,只会在几个子线程之间发挥作用
3、主线程和线程池之间没有直接关系,线程池使用自己的线程。生命周期也相互独立。
4、shutdown()可以理解为:主线程要求线程池关闭,但不会为此等待线程池执行完毕。
5、实际发挥了等待作用的并不是线程池所提供的能力(当然线程池也确实提供了这类能力),而是:position.acquireUninterruptibly(2) 这句话。
shutdown() 作为函数,当然是立即执行,也即是不再接受新任务了;但是它即不会强行终止正在执行的任务,也不会取消已经提交的任务。也就是说之前提交的5个任务,仍然会执行完毕,且跟主线程生命周期无关,也就是即便你直接在后面写上: if (1==1) return; 来立即结束主函数,你也会发现线程池的5个任务会顺利执行完毕。
6、另一个长得很像的函数是:
shutdownNow(),这个函数比shutdown()更狠,两点:
1)、对于尚未执行的任务,全部取消掉;
2)、对于正在执行的任务,发出interrupt()。
不过程序因为在发生异常时没有正确释放信号量(应该放在finally块中释放),所以如果改为shutdownNow()会出问题:主线程死等。


Java5 并发学习
ExecutorService中submit和execute的区别
java线程常见面试题
JAVA并发-显式锁(一)


	public List<DrugDpInfoVO> selectRecipeSumVO(final AlertMessageKeyword query, PageBreaker page, final Integer engineRunFlag) {
		List<DrugDpInfoVO> list = optAlertmessageStatisticMapper.selectRecipeSumVO(this.getBaseDBName(), query, page, engineRunFlag);

		if (null == list || list.isEmpty()) {
			log.warn("无匹配记录");
			return list;
		}

		//ExecutorService EXECUTORSERVICE = Executors.newFixedThreadPool(50);
		List<Future<DrugDpInfoVO>> listFuture = new ArrayList<>();

		try {
			for (final DrugDpInfoVO e : list) {
				Future<DrugDpInfoVO> future = EXECUTORSERVICE.submit(new Callable<DrugDpInfoVO>() {

					@Override
					public DrugDpInfoVO call() throws Exception {

						DrugDpInfoVO drugDpInfoVO = optAlertmessageStatisticMapper.selectSingleRecipeSumVO(getBaseDBName(), query, e, engineRunFlag);
						drugDpInfoVO.setAmount(e.getAmount());
						return drugDpInfoVO;

					}
				});

				listFuture.add(future);
			}

			list.clear();

			for (Future<DrugDpInfoVO> future : listFuture) {
				list.add(future.get());
			}

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		return list;
	}
分享到:
评论

相关推荐

    JAVA主线程等待子线程执行完毕再执行[参照].pdf

    这种方式更加符合人们的胃口,即子线程执行完毕后,主线程会被通知,于是主线程可以继续执行。 JoinDemo JoinDemo 是一种被动式的实现方式。在这个示例中,我们创建了一个子线程,并启动了子线程。主线程处理其他...

    Java使用ExecutorService来停止线程服务

    shutdown() 方法会正常关闭线程池,等待所有任务执行完毕后关闭,而 shutdownNow() 方法会强行关闭线程池,取消所有正在执行的任务。 使用 shutdown() 方法来停止线程服务 ----------------------------- shutdown...

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

    当所有任务执行完毕后,ExecutorService将被关闭。此外,ExecutorService的submit()方法返回一个Future对象,可以用来检查任务的状态(是否完成)、获取结果或取消任务。 ExecutorService的主要方法包括: - `...

    Java多线程--等待所有子线程执行完的五种方法.docx

    在Java多线程编程中,有时我们需要确保所有子线程执行完毕后再进行后续操作,例如在并发测试、数据聚合或资源清理等场景。本篇文章将详细介绍五种在Java中等待所有子线程执行完的方法。 ### 方法一:使用`sleep`...

    多线程执行完后主程序再执行(包括需要子线程返回结果)

    本文将详细探讨如何在多线程环境中确保所有子线程执行完毕后,主程序再进行后续操作,并且如何获取子线程的返回结果。这涉及到线程的同步与通信,是理解并发编程的关键点。 首先,多线程执行时,主线程会创建并启动...

    JAVA多线程框架.pdf

    需要注意的是,`shutdown()`并不会阻塞调用它的主线程,因此如果需要等待所有任务执行完毕,可以使用`ExecutorService.shutdownNow()`或`ExecutorService.awaitTermination()`。 定时任务是另一个关键特性,Java....

    Java中多线程的使用线程池.docx

    - **关闭线程池**:在所有任务执行完毕后,调用 `executorService.shutdown()` 或 `executorService.shutdownNow()` 来优雅地关闭线程池。 6. **示例代码**: - `MyThread` 类实现了`Runnable`接口,`run`方法...

    java线程池常用方法.docx

    在使用完毕后,应当关闭线程池以释放资源。这可以通过`shutdown()`或`shutdownNow()`方法来实现: - `shutdown()`:不会立即中断正在执行的任务,但不再接收新任务。当所有任务完成后,线程池会自动关闭。 ```...

    java多线程处理数据(csdn)————程序.pdf

    在所有任务执行完毕后,应关闭线程池以释放资源,防止资源泄漏。 总的来说,这个程序展示了如何利用Java的并发特性来处理大数据量的查询任务。通过拆分任务,创建线程池并发执行,然后合并结果,有效地提高了程序的...

    ExecutorService线程池

    3. **关闭线程池**:任务执行完毕后,应调用`shutdown()`或`shutdownNow()`方法来停止接收新任务,并等待正在执行的任务完成。`shutdown()`会等待已提交任务执行完毕,而`shutdownNow()`尝试停止所有正在执行的任务...

    javamail多线程群发

    在“javamail 多线程群发”的场景中,我们通常会创建一个线程池,例如使用Java的ExecutorService,来并发执行多个邮件发送任务。以下是一个简化的步骤概述: 1. **初始化JavaMail Session**:首先,我们需要设置...

    Java ExcutorService优雅关闭方式解析

    优雅关闭ExecutorService意味着不仅要停止新任务的提交,还要等待正在执行的任务完成,或者在超时后强制停止。这里我们将详细讨论如何实现这一目标。 首先,`ExecutorService.shutdown()`方法是关闭ExecutorService...

    控制多个线程结束,后再执行统计结果

    这篇博客“控制多个线程结束,后再执行统计结果”很可能探讨了如何在多线程环境中,等待所有子线程执行完毕后,再执行最后的统计操作。 线程同步的主要目的是防止数据竞争和死锁,确保共享资源的安全访问。Java提供...

    Java简单实现“主线程等待所有子线程完成再继续”

    有时我们可能需要设计程序,使得主线程在执行过程中能够等待所有子线程完成后再继续执行。这种需求常见于需要同步多个并行任务或者在主任务结束前确保所有子任务已经处理完毕的场景。本文将详细解释如何使用Java实现...

    Java多线程之Executor框架.docx

    `ExecutorService`提供了`shutdown()`和`shutdownNow()`方法来关闭线程池,前者等待所有任务执行完毕,后者则尝试停止未开始的任务并返回尚未开始的任务列表。`isShutdown()`和`isTerminated()`方法分别检查线程池...

    2_ExecutorService源码阅读1

    isTerminated() 方法在所有任务执行完毕并成功关闭后返回 true,注意它在没有调用 shutdown 或 shutdownNow 之前总是返回 false。 **awaitTermination() 方法** 这个方法阻塞当前线程,直到所有在调用 shutdown() ...

Global site tag (gtag.js) - Google Analytics