├── .gitignore ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── snowcattle │ │ └── game │ │ ├── common │ │ ├── constants │ │ │ └── Loggers.java │ │ ├── enums │ │ │ └── BlockingQueueType.java │ │ └── utils │ │ │ └── ExecutorUtil.java │ │ └── thread │ │ ├── ThreadNameFactory.java │ │ ├── executor │ │ ├── NonOrderedQueuePoolExecutor.java │ │ └── OrderedQueuePoolExecutor.java │ │ ├── factory │ │ └── GameThreadPoolHelpFactory.java │ │ ├── policy │ │ ├── AbortPolicy.java │ │ ├── BlockingPolicy.java │ │ ├── CallerRunsPolicy.java │ │ ├── DiscardOldestPolicy.java │ │ ├── DiscardPolicy.java │ │ └── RejectedPolicyType.java │ │ └── worker │ │ ├── AbstractWork.java │ │ ├── OrderedQueuePool.java │ │ └── TasksQueue.java └── resources │ └── log4j.properties └── test └── java └── com └── snowcattle └── game └── thread ├── TestRunnable.java ├── TestRunnable2.java └── ThreadPoolTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.tar.gz 3 | logs/ 4 | .DS_Store 5 | .idea 6 | *.iml 7 | dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GameThreadPool 2 | 游戏中常用的线程池,顺序队列和非顺序队列 3 | 4 | - 作者qq 330258845 5 | - QQ群:310158485 6 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | www.snowcattle.com 8 | game-thread 9 | 1.1.5-SNAPSHOT 10 | 11 | 12 | 13 | jitpack.io 14 | https://jitpack.io 15 | 16 | 17 | 18 | 19 | UTF-8 20 | 1.7.12 21 | 4.12 22 | UTF-8 23 | 24 | 25 | 26 | 27 | 28 | 29 | junit 30 | junit 31 | ${junit.version} 32 | test 33 | 34 | 35 | 36 | 37 | org.slf4j 38 | slf4j-log4j12 39 | ${slf4j-log4j12.version} 40 | 41 | 42 | 43 | org.apache.commons 44 | commons-pool2 45 | 2.4.2 46 | 47 | 48 | commons-lang 49 | commons-lang 50 | 2.6 51 | 52 | 53 | 54 | commons-io 55 | commons-io 56 | 1.4 57 | 58 | 59 | 60 | 61 | com.github.jwpttcg66 62 | game-expression 63 | 1.1 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | src/main/resources 74 | 75 | **/* 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | org.apache.maven.plugins 84 | maven-compiler-plugin 85 | 3.1 86 | 87 | 1.7 88 | 1.7 89 | ${project.build.sourceEncoding} 90 | ${project.build.directory} 91 | 92 | 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-jar-plugin 97 | 2.4 98 | 99 | 100 | jar 101 | 102 | 103 | ${project.basedir}/target/classes 104 | 105 | com/** 106 | 107 | 108 | 109 | 110 | 111 | org.apache.maven.plugins 112 | maven-source-plugin 113 | 2.4 114 | 115 | 116 | attach-sources 117 | verify 118 | 119 | jar-no-fork 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/common/constants/Loggers.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.common.constants; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * 统一定义系统使用的slf4j的Logger 8 | * 9 | * 10 | */ 11 | public class Loggers { 12 | /**thread相关的日志 */ 13 | public static final Logger threadLogger = LoggerFactory.getLogger("thread"); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/common/enums/BlockingQueueType.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.common.enums; 2 | 3 | /** 4 | * Created by jiangwenping on 2017/6/5. 5 | */ 6 | public enum BlockingQueueType { 7 | LINKED_BLOCKING_QUEUE("LinkedBlockingQueue"), 8 | ARRAY_BLOCKING_QUEUE("ArrayBlockingQueue"), 9 | SYNCHRONOUS_QUEUE("SynchronousQueue"); 10 | 11 | private String value; 12 | 13 | private BlockingQueueType(String value) { 14 | this.value = value; 15 | } 16 | 17 | public String getValue() { 18 | return value; 19 | } 20 | 21 | public static BlockingQueueType fromString(String value) { 22 | for (BlockingQueueType type : BlockingQueueType.values()) { 23 | if (type.getValue().equalsIgnoreCase(value.trim())) { 24 | return type; 25 | } 26 | } 27 | 28 | throw new IllegalArgumentException("Mismatched type with value=" + value); 29 | } 30 | 31 | public String toString() { 32 | return value; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/common/utils/ExecutorUtil.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.common.utils; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | 11 | /** 12 | * Created by jiangwenping on 17/4/10. 13 | */ 14 | public class ExecutorUtil { 15 | private static final Logger logger = Loggers.threadLogger; 16 | /** 默认的{@link ExecutorService}关闭前等待其中的任务结束的时间:5分钟 */ 17 | private static final int DEFAULT_AWAIT_TERMINATE_MINUTES = 5; 18 | 19 | /** 20 | * 关闭{@link ExecutorService},在关闭之前最多等待 21 | * {@link #DEFAULT_AWAIT_TERMINATE_MINUTES}分钟来满足其中已经开始任务结束 22 | * 23 | * @param executorService 24 | * @return 返回停止后仍然为被开始执行的任务 25 | * @see {@link #shutdownAndAwaitTermination(ExecutorService, long, TimeUnit)} 26 | */ 27 | public static List shutdownAndAwaitTermination(final ExecutorService executorService) { 28 | return shutdownAndAwaitTermination(executorService, DEFAULT_AWAIT_TERMINATE_MINUTES, TimeUnit.MINUTES); 29 | } 30 | /** 31 | * 关闭{@link ExecutorService},在指定的时间内awaitTermateTimeout等待 32 | * executorService中已经开始的任务尽量结束. 此实现参照{@link ExecutorService} 33 | * 注释中的 shutdownAndAwaitTermination策略 34 | * 35 | * @param executorService 36 | * 将要被停止的{@link ExecutorService} 37 | * @param awaitTerminateTimeout 38 | * 等待时间 39 | * @param timeUnit 40 | * awaitTerminate的单位 41 | * @return 返回停止后任然未被开始执行的任务 42 | */ 43 | public static List shutdownAndAwaitTermination(final ExecutorService executorService, 44 | final long awaitTerminateTimeout, final TimeUnit timeUnit) { 45 | List _left = null; 46 | executorService.shutdown(); 47 | try { 48 | boolean _terminateResult = executorService.awaitTermination(awaitTerminateTimeout, timeUnit); 49 | if (logger.isInfoEnabled()) { 50 | logger.info("[#ExecutorUtil.safeShudown] [Shutdown " + executorService + " " 51 | + (_terminateResult ? "Success" : "Fail") + "]"); 52 | } 53 | if (!_terminateResult) { 54 | //再次停止 55 | _left = executorService.shutdownNow(); 56 | if (_left != null) { 57 | for (Runnable _o : _left) { 58 | logger.warn("Left runnable :" + _o); 59 | } 60 | } 61 | _terminateResult = executorService.awaitTermination(awaitTerminateTimeout, timeUnit); 62 | if (logger.isInfoEnabled()) { 63 | logger.info("[#ExecutorUtil.shutdownAndAwaitTermination] [ShutdwonNow " + executorService + " " 64 | + (_terminateResult ? "Success" : "Fail") + "]"); 65 | } 66 | } 67 | } catch (InterruptedException e) { 68 | if (logger.isErrorEnabled()) { 69 | logger.error("[#ExecutorUtil.shutdownAndAwaitTermination] [ShutdwonNow " + executorService + " " 70 | + "error]" + e.toString(), e); 71 | } 72 | _left = executorService.shutdownNow(); 73 | Thread.currentThread().interrupt(); 74 | } 75 | return _left; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/ThreadNameFactory.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | /** 7 | * @author jwp 8 | * 线程名字工厂 9 | */ 10 | public class ThreadNameFactory implements ThreadFactory{ 11 | private ThreadGroup group; 12 | private AtomicInteger threadNumber = new AtomicInteger(0); 13 | private String namePrefix; 14 | private boolean daemon; 15 | 16 | public ThreadNameFactory(String namePreFix) 17 | { 18 | this(namePreFix, false); 19 | } 20 | 21 | public ThreadNameFactory(String namePreFix, boolean daemon) 22 | { 23 | SecurityManager s = System.getSecurityManager(); 24 | group = (s != null) ? s.getThreadGroup() : Thread.currentThread() 25 | .getThreadGroup(); 26 | this.namePrefix = namePreFix + "-thread-"; 27 | this.daemon = daemon; 28 | } 29 | 30 | public Thread newThread(Runnable r) 31 | { 32 | Thread t = new Thread(group, r, namePrefix 33 | + threadNumber.getAndIncrement(), 0); 34 | if(daemon) { 35 | t.setDaemon(daemon); 36 | }else{ 37 | if (t.isDaemon()) 38 | t.setDaemon(false); 39 | if (t.getPriority() != Thread.NORM_PRIORITY) 40 | t.setPriority(Thread.NORM_PRIORITY); 41 | } 42 | return t; 43 | } 44 | 45 | public String getNamePrefix() { 46 | return namePrefix; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/executor/NonOrderedQueuePoolExecutor.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.executor; 2 | 3 | /** 4 | * Created by jiangwenping on 17/3/10. 5 | */ 6 | 7 | 8 | import com.snowcattle.game.thread.ThreadNameFactory; 9 | import com.snowcattle.game.thread.worker.AbstractWork; 10 | 11 | import java.util.concurrent.*; 12 | 13 | /** 14 | * 无序队列线程池 15 | * @author zhaohui 16 | * 17 | */ 18 | public class NonOrderedQueuePoolExecutor extends ThreadPoolExecutor { 19 | 20 | public NonOrderedQueuePoolExecutor(int corePoolSize) { 21 | super(corePoolSize, corePoolSize*2, 30, TimeUnit.SECONDS, 22 | new LinkedBlockingQueue()); 23 | } 24 | 25 | public NonOrderedQueuePoolExecutor(String name, int corePoolSize) { 26 | super(corePoolSize, corePoolSize*2, 30, TimeUnit.SECONDS, 27 | new LinkedBlockingQueue(), new ThreadNameFactory(name)); 28 | } 29 | 30 | public NonOrderedQueuePoolExecutor(String name, int corePoolSize, int maxPoolSize) { 31 | super(corePoolSize, maxPoolSize, 30, TimeUnit.SECONDS, 32 | new LinkedBlockingQueue(), new ThreadNameFactory(name)); 33 | } 34 | 35 | public NonOrderedQueuePoolExecutor(String name, int corePoolSize, int maxSize, RejectedExecutionHandler rejectedExecutionHandler) { 36 | super(corePoolSize, maxSize, 30, TimeUnit.SECONDS, 37 | new LinkedBlockingQueue(), new ThreadNameFactory(name), rejectedExecutionHandler); 38 | } 39 | 40 | 41 | public NonOrderedQueuePoolExecutor(String name, int corePoolSize, int maxSize, BlockingQueue blockingQueue, RejectedExecutionHandler rejectedExecutionHandler) { 42 | super(corePoolSize, maxSize, 30, TimeUnit.SECONDS, 43 | blockingQueue, new ThreadNameFactory(name), rejectedExecutionHandler); 44 | } 45 | 46 | public void executeWork(AbstractWork work) { 47 | execute(work); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/executor/OrderedQueuePoolExecutor.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.executor; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import com.snowcattle.game.common.enums.BlockingQueueType; 5 | import com.snowcattle.game.thread.ThreadNameFactory; 6 | import com.snowcattle.game.thread.worker.AbstractWork; 7 | import com.snowcattle.game.thread.worker.OrderedQueuePool; 8 | import com.snowcattle.game.thread.worker.TasksQueue; 9 | import org.slf4j.Logger; 10 | 11 | import java.util.concurrent.*; 12 | 13 | /** 14 | * Created by jiangwenping on 17/3/10. 15 | */ 16 | public class OrderedQueuePoolExecutor extends ThreadPoolExecutor { 17 | 18 | protected Logger logger = Loggers.threadLogger; 19 | 20 | private OrderedQueuePool pool = new OrderedQueuePool(); 21 | 22 | private int maxTaskQueueSize; 23 | private ThreadNameFactory threadNameFactory; 24 | 25 | public OrderedQueuePoolExecutor(String name, int corePoolSize, 26 | int maxTaskQueueSize) { 27 | super(corePoolSize, 2 * corePoolSize, 30, TimeUnit.SECONDS, 28 | new LinkedBlockingQueue(), new ThreadNameFactory(name)); 29 | this.maxTaskQueueSize = maxTaskQueueSize; 30 | this.threadNameFactory = (ThreadNameFactory) getThreadFactory(); 31 | } 32 | 33 | public OrderedQueuePoolExecutor(String name, int corePoolSize, int maxPoolSize, 34 | int maxTaskQueueSize, RejectedExecutionHandler rejectedExecutionHandler) { 35 | super(corePoolSize, maxPoolSize, 30, TimeUnit.SECONDS, 36 | new LinkedBlockingQueue(), new ThreadNameFactory(name), rejectedExecutionHandler); 37 | this.maxTaskQueueSize = maxTaskQueueSize; 38 | this.threadNameFactory = (ThreadNameFactory) getThreadFactory(); 39 | } 40 | 41 | public OrderedQueuePoolExecutor(String name, int corePoolSize, 42 | int maxTaskQueueSize, RejectedExecutionHandler rejectedExecutionHandler) { 43 | super(corePoolSize, 2 * corePoolSize, 30, TimeUnit.SECONDS, 44 | new LinkedBlockingQueue(), new ThreadNameFactory(name), rejectedExecutionHandler); 45 | this.maxTaskQueueSize = maxTaskQueueSize; 46 | this.threadNameFactory = (ThreadNameFactory) getThreadFactory(); 47 | } 48 | 49 | public OrderedQueuePoolExecutor(String name, int corePoolSize, 50 | int maxTaskQueueSize, BlockingQueue blockingQueue, RejectedExecutionHandler rejectedExecutionHandler) { 51 | super(corePoolSize, 2 * corePoolSize, 30, TimeUnit.SECONDS, 52 | blockingQueue, new ThreadNameFactory(name), rejectedExecutionHandler); 53 | this.maxTaskQueueSize = maxTaskQueueSize; 54 | this.threadNameFactory = (ThreadNameFactory) getThreadFactory(); 55 | } 56 | 57 | /** 58 | * 增加执行任务 59 | * 60 | * @param key 61 | * @param value 62 | * @return 63 | */ 64 | public boolean addTask(long key, AbstractWork task) { 65 | TasksQueue queue = pool.getTasksQueue(key); 66 | boolean run = false; 67 | boolean result = false; 68 | synchronized (queue) { 69 | if (maxTaskQueueSize > 0) { 70 | if (queue.size() > maxTaskQueueSize) { 71 | // logger.error("队列" + threadNameFactory.getNamePrefix() + "(" + key + ")" + "抛弃指令!"); 72 | // queue.clear(); 73 | //不可以清空队列里的任务 74 | if (logger.isWarnEnabled()) { 75 | logger.warn("队列" + threadNameFactory.getNamePrefix() + "(" + key + ")" + "超过最大队列大小设置!"); 76 | } 77 | } 78 | } 79 | result = queue.add(task); 80 | if (result) { 81 | task.setTasksQueue(queue); 82 | { 83 | if (queue.isProcessingCompleted()) { 84 | queue.setProcessingCompleted(false); 85 | run = true; 86 | } 87 | } 88 | } else { 89 | logger.error("队列添加任务失败"); 90 | } 91 | } 92 | if (run) { 93 | execute(queue.poll()); 94 | } 95 | return result; 96 | } 97 | 98 | @Override 99 | protected void afterExecute(Runnable r, Throwable t) { 100 | super.afterExecute(r, t); 101 | 102 | AbstractWork work = (AbstractWork) r; 103 | TasksQueue queue = work.getTasksQueue(); 104 | if (queue != null) { 105 | AbstractWork afterWork = null; 106 | synchronized (queue) { 107 | afterWork = queue.poll(); 108 | if (afterWork == null) { 109 | queue.setProcessingCompleted(true); 110 | } 111 | } 112 | if (afterWork != null) { 113 | execute(afterWork); 114 | } 115 | } else { 116 | logger.error("执行队列为空"); 117 | } 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/factory/GameThreadPoolHelpFactory.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.factory; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import com.snowcattle.game.common.enums.BlockingQueueType; 5 | import com.snowcattle.game.thread.ThreadNameFactory; 6 | import com.snowcattle.game.thread.policy.*; 7 | import org.slf4j.Logger; 8 | 9 | import java.util.concurrent.*; 10 | 11 | /** 12 | * Created by jiangwenping on 2017/6/5. 13 | * 游戏线程池辅助工厂 14 | */ 15 | public class GameThreadPoolHelpFactory { 16 | 17 | public RejectedExecutionHandler createPolicy(RejectedPolicyType rejectedPolicyType) { 18 | 19 | switch (rejectedPolicyType) { 20 | case BLOCKING_POLICY: 21 | return new BlockingPolicy(); 22 | case CALLER_RUNS_POLICY: 23 | return new CallerRunsPolicy(); 24 | case ABORT_POLICY: 25 | return new AbortPolicy(); 26 | case DISCARD_POLICY: 27 | return new DiscardPolicy(); 28 | case DISCARD_OLDEST_POLICY: 29 | return new DiscardOldestPolicy(); 30 | } 31 | 32 | return null; 33 | } 34 | 35 | public RejectedExecutionHandler createPolicy(RejectedPolicyType rejectedPolicyType, String threadName) { 36 | 37 | switch (rejectedPolicyType) { 38 | case BLOCKING_POLICY: 39 | return new BlockingPolicy(threadName); 40 | case CALLER_RUNS_POLICY: 41 | return new CallerRunsPolicy(threadName); 42 | case ABORT_POLICY: 43 | return new AbortPolicy(threadName); 44 | case DISCARD_POLICY: 45 | return new DiscardPolicy(threadName); 46 | case DISCARD_OLDEST_POLICY: 47 | return new DiscardOldestPolicy(threadName); 48 | } 49 | 50 | return null; 51 | } 52 | 53 | public BlockingQueue createBlockingQueue(BlockingQueueType blockingQueueType, int queues) { 54 | 55 | switch (blockingQueueType) { 56 | case LINKED_BLOCKING_QUEUE: 57 | return new LinkedBlockingQueue(); 58 | case ARRAY_BLOCKING_QUEUE: 59 | return new ArrayBlockingQueue(queues); 60 | case SYNCHRONOUS_QUEUE: 61 | return new SynchronousQueue(); 62 | } 63 | 64 | return null; 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/policy/AbortPolicy.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.policy; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.concurrent.ThreadPoolExecutor; 7 | 8 | /** 9 | * Created by jwp on 2017/3/8. 10 | */ 11 | public class AbortPolicy extends ThreadPoolExecutor.AbortPolicy { 12 | private static final Logger logger = Loggers.threadLogger; 13 | 14 | 15 | private String threadName; 16 | 17 | public AbortPolicy() { 18 | this(null); 19 | } 20 | 21 | public AbortPolicy(String threadName) { 22 | this.threadName = threadName; 23 | } 24 | 25 | public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { 26 | if (threadName != null) { 27 | logger.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); 28 | } 29 | String msg = String.format("Server[" 30 | + " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," 31 | + " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s)]", 32 | threadName, executor.getPoolSize(), executor.getActiveCount(), executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getLargestPoolSize(), 33 | executor.getTaskCount(), executor.getCompletedTaskCount(), executor.isShutdown(), executor.isTerminated(), executor.isTerminating()); 34 | super.rejectedExecution(runnable, executor); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/policy/BlockingPolicy.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.policy; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.concurrent.RejectedExecutionHandler; 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | 9 | /** 10 | * Created by jwp on 2017/3/8. 11 | * 阻塞 12 | */ 13 | 14 | public class BlockingPolicy implements RejectedExecutionHandler { 15 | private static final Logger logger = Loggers.threadLogger; 16 | 17 | private String threadName; 18 | 19 | public BlockingPolicy() { 20 | this(null); 21 | } 22 | 23 | public BlockingPolicy(String threadName) { 24 | this.threadName = threadName; 25 | } 26 | 27 | public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { 28 | if (threadName != null) { 29 | logger.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); 30 | } 31 | 32 | if (!executor.isShutdown()) { 33 | try { 34 | executor.getQueue().put(runnable); 35 | } catch (InterruptedException e) { 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/policy/CallerRunsPolicy.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.policy; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.concurrent.ThreadPoolExecutor; 7 | 8 | /** 9 | * Created by jwp on 2017/3/8. 10 | */ 11 | public class CallerRunsPolicy extends ThreadPoolExecutor.CallerRunsPolicy { 12 | private static final Logger logger = Loggers.threadLogger; 13 | 14 | private String threadName; 15 | 16 | public CallerRunsPolicy() { 17 | this(null); 18 | } 19 | 20 | public CallerRunsPolicy(String threadName) { 21 | this.threadName = threadName; 22 | } 23 | 24 | public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { 25 | if (threadName != null) { 26 | logger.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); 27 | } 28 | 29 | super.rejectedExecution(runnable, executor); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/policy/DiscardOldestPolicy.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.policy; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.concurrent.ThreadPoolExecutor; 7 | 8 | /** 9 | * Created by jwp on 2017/3/8. 10 | */ 11 | public class DiscardOldestPolicy extends ThreadPoolExecutor.DiscardOldestPolicy { 12 | private static final Logger logger = Loggers.threadLogger; 13 | 14 | private String threadName; 15 | 16 | public DiscardOldestPolicy() { 17 | this(null); 18 | } 19 | 20 | public DiscardOldestPolicy(String threadName) { 21 | this.threadName = threadName; 22 | } 23 | 24 | public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { 25 | if (threadName != null) { 26 | logger.error("Thread pool [{}] is exhausted, executor={}", threadName, executor.toString()); 27 | } 28 | 29 | super.rejectedExecution(runnable, executor); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/policy/DiscardPolicy.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.policy; 2 | 3 | import com.snowcattle.game.common.constants.Loggers; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.concurrent.ThreadPoolExecutor; 7 | 8 | /** 9 | * Created by jwp on 2017/3/8. 10 | */ 11 | public class DiscardPolicy extends ThreadPoolExecutor.DiscardPolicy { 12 | private static final Logger logger = Loggers.threadLogger; 13 | 14 | private final String threadName; 15 | 16 | public DiscardPolicy() { 17 | this(null); 18 | } 19 | 20 | public DiscardPolicy(String threadName) { 21 | this.threadName = threadName; 22 | } 23 | 24 | public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { 25 | if (threadName != null) { 26 | logger.error("hread pool [{}] is exhausted, executor={}", threadName, executor.toString()); 27 | } 28 | 29 | super.rejectedExecution(runnable, executor); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/policy/RejectedPolicyType.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.policy; 2 | 3 | /** 4 | * Created by jwp on 2017/3/8. 5 | * 线程的拒绝类型 6 | * 7 | * 8 | * 1) 默认的ThreadPoolExecutor.AbortPolicy 处理程序遭到拒绝将抛出运行时RejectedExecutionException; 9 | (2) ThreadPoolExecutor.CallerRunsPolicy 线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度 10 | (3) ThreadPoolExecutor.DiscardPolicy 不能执行的任务将被删除; 11 | (4) ThreadPoolExecutor.DiscardOldestPolicy 如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。 12 | 13 | */ 14 | public enum RejectedPolicyType { 15 | /**丢弃*/ 16 | ABORT_POLICY("AbortPolicy"), 17 | /*阻塞*/ 18 | BLOCKING_POLICY("BlockingPolicy"), 19 | /*直接运行*/ 20 | CALLER_RUNS_POLICY("CallerRunsPolicy"), 21 | /*抛弃老的*/ 22 | DISCARD_OLDEST_POLICY("DiscardOldestPolicy"), 23 | /*删除*/ 24 | DISCARD_POLICY("DiscardPolicy"); 25 | private String value; 26 | 27 | private RejectedPolicyType(String value) { 28 | this.value = value; 29 | } 30 | 31 | public String getValue() { 32 | return value; 33 | } 34 | 35 | public static RejectedPolicyType fromString(String value) { 36 | for (RejectedPolicyType type : RejectedPolicyType.values()) { 37 | if (type.getValue().equalsIgnoreCase(value.trim())) { 38 | return type; 39 | } 40 | } 41 | 42 | throw new IllegalArgumentException("Mismatched type with value=" + value); 43 | } 44 | 45 | public String toString() { 46 | return value; 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/worker/AbstractWork.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.worker; 2 | 3 | /** 4 | * Created by jiangwenping on 17/3/10. 5 | */ 6 | public abstract class AbstractWork implements Runnable { 7 | 8 | private TasksQueue tasksQueue; 9 | 10 | public TasksQueue getTasksQueue() { 11 | return tasksQueue; 12 | } 13 | 14 | public void setTasksQueue(TasksQueue tasksQueue) { 15 | this.tasksQueue = tasksQueue; 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/worker/OrderedQueuePool.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.worker; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | /** 6 | * Created by jiangwenping on 17/3/10. 7 | */ 8 | public class OrderedQueuePool { 9 | 10 | ConcurrentHashMap> map = new ConcurrentHashMap>(); 11 | 12 | /** 13 | * 获得任务队列 14 | * 15 | * @param key 16 | * @return 17 | */ 18 | public TasksQueue getTasksQueue(K key) { 19 | TasksQueue queue = map.get(key); 20 | 21 | if (queue == null) { 22 | TasksQueue newQueue = new TasksQueue(); 23 | queue = map.putIfAbsent(key, newQueue); 24 | if (queue == null) { 25 | queue = newQueue; 26 | } 27 | } 28 | 29 | return queue; 30 | } 31 | 32 | /** 33 | * 获得全部任务队列 34 | * 35 | * @param key 36 | * @return 37 | */ 38 | public ConcurrentHashMap> getTasksQueues() { 39 | return map; 40 | } 41 | 42 | /** 43 | * 移除任务队列 44 | * 45 | * @param key 46 | * @return 47 | */ 48 | public void removeTasksQueue(K key) { 49 | map.remove(key); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/snowcattle/game/thread/worker/TasksQueue.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread.worker; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.LinkedBlockingQueue; 5 | 6 | /** 7 | * Created by jiangwenping on 17/3/10. 8 | */ 9 | public class TasksQueue { 10 | 11 | /** 12 | * 命令队列 13 | */ 14 | private final BlockingQueue tasksQueue = new LinkedBlockingQueue(); 15 | 16 | private boolean processingCompleted = true; 17 | 18 | /** 19 | * 下一执行命令 20 | * 21 | * @return 22 | */ 23 | public V poll() { 24 | return tasksQueue.poll(); 25 | } 26 | 27 | /** 28 | * 增加执行指令 29 | * 30 | * @param command 31 | * @return 32 | */ 33 | public boolean add(V value) { 34 | return tasksQueue.add(value); 35 | } 36 | 37 | /** 38 | * 清理 39 | */ 40 | public void clear() { 41 | tasksQueue.clear(); 42 | } 43 | 44 | /** 45 | * 获取指令数量 46 | * 47 | * @return 48 | */ 49 | public int size() { 50 | return tasksQueue.size(); 51 | } 52 | 53 | public boolean isProcessingCompleted() { 54 | return processingCompleted; 55 | } 56 | 57 | public void setProcessingCompleted(boolean processingCompleted) { 58 | this.processingCompleted = processingCompleted; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=debug,stdout,error 2 | log4j.logger.thread=debug,thread 3 | 4 | #--------------------stdout-------------------------------- 5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 6 | log4j.appender.stdout.encoding=UTF-8 7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss} [%-5p] - %C{1}.%M - %m%n 9 | 10 | #--------------------error-------------------------------- 11 | log4j.appender.error=org.apache.log4j.DailyRollingFileAppender 12 | log4j.appender.error.Threshold=WARN 13 | log4j.appender.error.encoding=UTF-8 14 | log4j.appender.error.append=true 15 | log4j.appender.error.datePattern='.'yyyy-MM-dd 16 | log4j.appender.error.File=logs/error.log 17 | log4j.appender.error.layout=org.apache.log4j.PatternLayout 18 | log4j.appender.error.layout.ConversionPattern=%d{HH:mm:ss,SSS} - %C{1}.%M - %m%n 19 | log4j.appender.gameExecutorEvent.layout.ConversionPattern=%d{HH:mm:ss} - %m%n 20 | 21 | #--------------------thread-------------------------------- 22 | log4j.appender.thread=org.apache.log4j.DailyRollingFileAppender 23 | log4j.appender.thread.encoding=UTF-8 24 | log4j.appender.thread.append=true 25 | log4j.appender.thread.datePattern='.'yyyy-MM-dd 26 | log4j.appender.thread.File=logs/thread.log 27 | log4j.appender.thread.layout=org.apache.log4j.PatternLayout 28 | log4j.appender.thread.layout.ConversionPattern=%d{HH:mm:ss} - %m%n -------------------------------------------------------------------------------- /src/test/java/com/snowcattle/game/thread/TestRunnable.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * Created by jiangwenping on 2017/6/6. 7 | */ 8 | public class TestRunnable implements Runnable{ 9 | private static AtomicInteger atomicInteger = new AtomicInteger(); 10 | public void run() { 11 | try { 12 | System.out.println(atomicInteger.getAndIncrement()); 13 | Thread.sleep(1 * 1000); 14 | } catch (Exception e) { 15 | e.printStackTrace(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/snowcattle/game/thread/TestRunnable2.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread; 2 | 3 | /** 4 | * Created by jiangwenping on 2017/6/6. 5 | */ 6 | public class TestRunnable2 implements Runnable{ 7 | private int i; 8 | 9 | public TestRunnable2(int i) { 10 | this.i = i; 11 | } 12 | 13 | @Override 14 | public void run() { 15 | System.out.println(i); 16 | try { 17 | Thread.sleep(1 * 1000); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/snowcattle/game/thread/ThreadPoolTest.java: -------------------------------------------------------------------------------- 1 | package com.snowcattle.game.thread; 2 | 3 | import com.snowcattle.game.common.enums.BlockingQueueType; 4 | import com.snowcattle.game.thread.factory.GameThreadPoolHelpFactory; 5 | import com.snowcattle.game.thread.policy.RejectedPolicyType; 6 | 7 | import java.util.concurrent.*; 8 | 9 | import static java.util.concurrent.ThreadPoolExecutor.*; 10 | 11 | /** 12 | * Created by jiangwenping on 2017/6/6. 13 | */ 14 | public class ThreadPoolTest { 15 | 16 | public static void main(String[] args) throws Exception{ 17 | int coreSize = 1; 18 | int maxSize = 100; 19 | long time = 1; 20 | TimeUnit timeUnit = TimeUnit.SECONDS; 21 | LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(); 22 | ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(5); 23 | BlockingQueue blockingQueue = arrayBlockingQueue; 24 | ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(coreSize, maxSize, time, timeUnit, blockingQueue, rejectedExecutionHandler()); 25 | int threadSize = 100; 26 | for(int i = 0; i < threadSize; i++){ 27 | try { 28 | // threadPoolExecutor.execute(new TestRunnable()); 29 | threadPoolExecutor.execute(new TestRunnable2(i)); 30 | }catch (Exception e){ 31 | e.printStackTrace(); 32 | } 33 | } 34 | System.out.println("d"); 35 | } 36 | 37 | public static RejectedExecutionHandler rejectedExecutionHandler(){ 38 | GameThreadPoolHelpFactory gameThreadPoolHelpFactory = new GameThreadPoolHelpFactory(); 39 | RejectedPolicyType rejectedPolicyType = RejectedPolicyType.ABORT_POLICY; 40 | return gameThreadPoolHelpFactory.createPolicy(rejectedPolicyType, "test"); 41 | } 42 | } 43 | --------------------------------------------------------------------------------