/******************************************************************************* * Copyright (c) 2005, 2014 springside.github.io * * Licensed under the Apache License, Version 2.0 (the "License"); *******************************************************************************/ package org.springside.modules.utils.concurrent.threadpool; import static org.assertj.core.api.Assertions.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springside.modules.test.log.LogbackListAppender; import org.springside.modules.utils.concurrent.ThreadUtil; public class ThreadPoolUtilTest { @Test public void buildThreadFactory() { Runnable testRunnable = new Runnable() { @Override public void run() { } }; // 测试name格式 ThreadFactory threadFactory = ThreadPoolUtil.buildThreadFactory("example"); Thread thread = threadFactory.newThread(testRunnable); assertThat(thread.getName()).isEqualTo("example-0"); assertThat(thread.isDaemon()).isFalse(); // 测试daemon属性设置 threadFactory = ThreadPoolUtil.buildThreadFactory("example", true); Thread thread2 = threadFactory.newThread(testRunnable); assertThat(thread.getName()).isEqualTo("example-0"); assertThat(thread2.isDaemon()).isTrue(); } @Test public void gracefulShutdown() throws InterruptedException { Logger logger = LoggerFactory.getLogger("test"); LogbackListAppender appender = new LogbackListAppender(); appender.addToLogger("test"); // time enough to shutdown ExecutorService pool = Executors.newSingleThreadExecutor(); Runnable task = new Task(logger, 200, 0); pool.execute(task); ThreadPoolUtil.gracefulShutdown(pool, 1000, TimeUnit.MILLISECONDS); assertThat(pool.isTerminated()).isTrue(); assertThat(appender.getFirstLog()).isNull(); // time not enough to shutdown,call shutdownNow appender.clearLogs(); pool = Executors.newSingleThreadExecutor(); task = new Task(logger, 1000, 0); pool.execute(task); ThreadPoolUtil.gracefulShutdown(pool, 500, TimeUnit.MILLISECONDS); assertThat(pool.isTerminated()).isTrue(); assertThat(appender.getFirstLog().getMessage()).isEqualTo("InterruptedException"); // self thread interrupt while calling gracefulShutdown appender.clearLogs(); final ExecutorService self = Executors.newSingleThreadExecutor(); task = new Task(logger, 100000, 0); self.execute(task); final CountDownLatch lock = new CountDownLatch(1); Thread thread = new Thread(new Runnable() { @Override public void run() { lock.countDown(); ThreadPoolUtil.gracefulShutdown(self, 200000, TimeUnit.MILLISECONDS); } }); thread.start(); lock.await(); thread.interrupt(); ThreadUtil.sleep(500); assertThat(appender.getFirstLog().getMessage()).isEqualTo("InterruptedException"); ThreadPoolUtil.gracefulShutdown(null, 1000); ThreadPoolUtil.gracefulShutdown(null, 1000, TimeUnit.MILLISECONDS); } @Test public void wrapException() { ScheduledThreadPoolExecutor executor = ThreadPoolBuilder.scheduledPool().build(); ExceptionTask task = new ExceptionTask(); executor.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS); ThreadUtil.sleep(500); // 线程第一次跑就被中断 assertThat(task.counter.get()).isEqualTo(1); ThreadPoolUtil.gracefulShutdown(executor, 1000); //////// executor = ThreadPoolBuilder.scheduledPool().build(); ExceptionTask newTask = new ExceptionTask(); Runnable wrapTask = ThreadPoolUtil.safeRunnable(newTask); executor.scheduleAtFixedRate(wrapTask, 0, 100, TimeUnit.MILLISECONDS); ThreadUtil.sleep(500); assertThat(newTask.counter.get()).isGreaterThan(2); System.out.println("-------actual run:" + task.counter.get()); ThreadPoolUtil.gracefulShutdown(executor, 1000); } static class ExceptionTask implements Runnable { public AtomicInteger counter = new AtomicInteger(0); @Override public void run() { counter.incrementAndGet(); throw new RuntimeException("fail"); } } static class Task implements Runnable { private final Logger logger; private int runTime = 0; private final int sleepTime; Task(Logger logger, int sleepTime, int runTime) { this.logger = logger; this.sleepTime = sleepTime; this.runTime = runTime; } @Override public void run() { System.out.println("start task"); if (runTime > 0) { long start = System.currentTimeMillis(); while ((System.currentTimeMillis() - start) < runTime) { } } try { Thread.sleep(sleepTime); } catch (InterruptedException e) { logger.warn("InterruptedException"); } } } }