├── .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 |
--------------------------------------------------------------------------------