├── .github
└── FUNDING.yml
├── .gitignore
├── Document.md
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── magic
│ ├── db
│ ├── CustomSqlUtils.java
│ ├── MagicDBUtils.java
│ ├── SingleTableUtils.java
│ ├── conversion
│ │ ├── ConditionBuilder.java
│ │ ├── SqlBuilder.java
│ │ └── SqlConversion.java
│ └── model
│ │ ├── Condition.java
│ │ ├── PageModel.java
│ │ ├── PageParamModel.java
│ │ └── SqlBuilderModel.java
│ ├── processing
│ ├── MagicDataProcessing.java
│ ├── commons
│ │ ├── enums
│ │ │ ├── ConcurrentTaskResultEnum.java
│ │ │ └── ProducerAndConsumerEnum.java
│ │ └── helper
│ │ │ └── ProcessingHelper.java
│ ├── concurrent
│ │ ├── collection
│ │ │ ├── ConcurrentCollectionAsync.java
│ │ │ ├── ConcurrentCollectionGroupRunner.java
│ │ │ ├── ConcurrentCollectionRunner.java
│ │ │ └── ConcurrentCollectionSync.java
│ │ ├── map
│ │ │ ├── ConcurrentMapAsync.java
│ │ │ ├── ConcurrentMapGroupRunner.java
│ │ │ ├── ConcurrentMapRunner.java
│ │ │ └── ConcurrentMapSync.java
│ │ └── task
│ │ │ ├── ConcurrentTaskCall.java
│ │ │ └── ConcurrentTaskSync.java
│ └── pac
│ │ ├── MagicConsumer.java
│ │ ├── MagicProducer.java
│ │ ├── MagicProducerAndConsumerManager.java
│ │ └── TaskData.java
│ ├── properties
│ ├── MagicProperties.java
│ ├── cache
│ │ └── PropertiesCacheManager.java
│ ├── enums
│ │ └── ReadMode.java
│ └── load
│ │ ├── LoadProperties.java
│ │ └── PropertiesEach.java
│ └── util
│ ├── CollectionUtils.java
│ ├── JSONUtil.java
│ ├── MapsUtil.java
│ └── StringUtils.java
└── test
└── java
└── com
└── magic
└── demo
├── db
└── SqlBuilderTest.java
├── json
├── TestEntity.java
├── TestEntity2.java
└── TestJsonUtil.java
├── processing
├── concurrent
│ ├── collcetion
│ │ ├── DemoAsyncProcessingCollection.java
│ │ └── DemoSyncProcessingCollection.java
│ ├── map
│ │ ├── DemoAsyncProcessingMap.java
│ │ └── DemoSyncProcessingMap.java
│ └── task
│ │ └── DemoConcurrentTaskSync.java
└── pac
│ ├── DemoConsumerOne.java
│ ├── DemoConsumerThree.java
│ ├── DemoConsumerTwo.java
│ ├── DemoProducerOne.java
│ ├── DemoProducerTwo.java
│ └── ProducerAndConsumerDemo.java
└── properties
└── MagicPropertiesDemo.java
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # yuyenews
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ['https://afdian.com/a/magicianio','https://magician-io.com/sponsor/sponsor.html','https://www.paypal.me/yuye666']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 | !**/src/main/**/build/
32 | !**/src/test/**/build/
33 |
34 | ### VS Code ###
35 | .vscode/
36 |
37 | ### Mac OS ###
38 | .DS_Store
39 |
40 | .idea
41 | .idea/
--------------------------------------------------------------------------------
/Document.md:
--------------------------------------------------------------------------------
1 | # Magic
2 |
3 | ## 运行环境
4 |
5 | JDK17+
6 |
7 | ## 初始化配置
8 |
9 | ### 导入依赖
10 |
11 | ```xml
12 |
13 | com.github.yuyenews
14 | Magic
15 | 1.0.3
16 |
17 | ```
18 |
19 | ## 并发处理任务
20 |
21 | ```java
22 | MagicDataProcessing.getConcurrentTaskSync()
23 | .setTimeout(1000) // 超时时间
24 | .setTimeUnit(TimeUnit.MILLISECONDS) // 超时时间的单位
25 | .add(() -> { // 添加一个任务
26 |
27 | // 在这里可以写上任务的业务逻辑
28 |
29 | }, (result, e) -> {
30 | // 此任务处理后的回调
31 | if(result.equals(ConcurrentTaskResultEnum.FAIL)){
32 | // 任务失败,此时e里面有详细的异常信息
33 | } else if(result.equals(ConcurrentTaskResultEnum.SUCCESS)) {
34 | // 任务成功,此时e是空的
35 | }
36 | })
37 | .add(() -> { // 添加一个任务
38 |
39 | // 在这里可以写上任务的业务逻辑
40 |
41 | }, (result, e) -> {
42 | // 此任务处理后的回调
43 | if(result.equals(ConcurrentTaskResultEnum.FAIL)){
44 | // 任务失败,此时e里面有详细的异常信息
45 | } else if(result.equals(ConcurrentTaskResultEnum.SUCCESS)) {
46 | // 任务成功,此时e是空的
47 | }
48 | })
49 | .start();
50 | ```
51 |
52 | 添加进去的任务会并发执行,但是在它们执行完之前,这整个代码块会同步等待在这,一直等到所有任务执行完或者超时才会继续往下走。
53 |
54 | 这里面的超时时间就是用来设置同步等待多久的。
55 |
56 | - 如果设置为0表示一直等到所有任务完成为止
57 | - 设置为大于0的时候,表示只等待这么久
58 |
59 |
60 |
61 | ## 并发处理List,Set等所有Collection类的集合里的元素
62 |
63 | ### 同步执行
64 |
65 | 假如有一个List需要并发处理里面的元素
66 |
67 | ```java
68 | List dataList = new ArrayList<>();
69 | ```
70 |
71 | 只需要将他传入syncRunner方法即可
72 |
73 | ```java
74 | MagicDataProcessing.getConcurrentCollectionSync()
75 | .syncRunner(dataList, data -> {
76 |
77 | // 这里可以拿到List里的元素,进行处理
78 | // List里的元素是什么类型,这个data就是什么类型
79 | System.out.println(data);
80 |
81 | },
82 | 10, // 每组多少条元素
83 | 1, // 每组之间同步等待多久
84 | TimeUnit.MINUTES // 等待的时间单位
85 | );
86 | ```
87 |
88 | 这个方法会将传进去的集合分成若干组,每组的大小由参数指定。
89 |
90 | 这些组会排队执行,但是每一组在执行的时候都是并发的,里面的每一个元素都会由单独的线程去处理。
91 |
92 | 需要等一组处理完了,才会处理下一组,但是有时候我们不想这么死板的等待,所以可以设置一个超时时间,超过了这个期限就不等了,直接进行下一组,所以这里的最后两个参数就是用来设置这个期限的。
93 |
94 | #### 也可以让每一组单独占一个线程
95 |
96 | ```java
97 | // 也可以用syncGroupRunner方法
98 | MagicDataProcessing.getConcurrentCollectionSync()
99 | .syncGroupRunner(dataList, data -> {
100 |
101 | // 这里是每一组List
102 | for(String item : data){
103 | // 这里可以拿到List里的元素,进行处理
104 | System.out.println(data);
105 | }
106 |
107 | },
108 | 10, // 每组多少条元素
109 | 1, // 每组之间同步等待多久
110 | TimeUnit.MINUTES // 等待的时间单位
111 | );
112 | ```
113 |
114 | 这个方法会将传进去的集合分成若干组,每组的大小由参数指定。
115 |
116 | 每一组由单独的线程处理。
117 |
118 | 会一直同步等待在这里,直到所有组都处理完了才会进行下一步,但是有时候我们不想这么死板的等待,所以可以设置一个超时时间,超过了这个期限就不等了,直接执行下一步。所以这里的最后两个参数就是用来设置这个期限的。
119 |
120 | ### 异步执行
121 |
122 | 其实就是将上面【同步执行】的代码放到了一个线程里,内部处理依然是上面【同步执行】的逻辑,但是这整个代码块将会异步执行,不需要等在这。所以个别相同的参数就不再重复解释了。
123 |
124 | ```java
125 | // 假如有一个List需要并发处理里面的元素
126 | List dataList = new ArrayList<>();
127 | ```
128 |
129 | #### 每个元素并发执行
130 |
131 | ```java
132 | // 只需要将他传入asyncRunner方法即可
133 | MagicDataProcessing.ConcurrentCollectionAsync().asyncRunner(dataList, data -> {
134 |
135 | // 这里可以拿到List里的元素,进行处理
136 | System.out.println(data);
137 |
138 | },
139 | 10, // 每组多少条元素
140 | 1, // 每组之间同步等待多久
141 | TimeUnit.MINUTES // 等待的时间单位
142 | )
143 | .start();// 注意,异步执行需要调用start方法
144 | ```
145 |
146 | 还可以这样写
147 |
148 | ```java
149 | MagicDataProcessing.ConcurrentCollectionAsync().asyncRunner(dataList, data -> {
150 |
151 | // 这里是每一组List
152 | for(String item : data){
153 | // 这里可以拿到List里的元素,进行处理
154 | System.out.println(data);
155 | }
156 |
157 | },
158 | 10, // 每组多少条元素
159 | 1, // 每组之间同步等待多久
160 | TimeUnit.MINUTES // 等待的时间单位
161 | ).asyncRunner(dataList2, data -> {
162 |
163 | // 这里可以拿到List里的元素,进行处理
164 | System.out.println(data);
165 |
166 | },
167 | 10, // 每组多少条元素
168 | 1, // 每组之间同步等待多久
169 | TimeUnit.MINUTES // 等待的时间单位
170 | ).asyncRunner(dataList3, data -> {
171 |
172 | // 这里可以拿到List里的元素,进行处理
173 | System.out.println(data);
174 |
175 | },
176 | 10, // 每组多少条元素
177 | 1, // 每组之间同步等待多久
178 | TimeUnit.MINUTES // 等待的时间单位
179 | )
180 | .start(); // 一样要调用start方法
181 | ```
182 |
183 | #### 每一组并发执行
184 |
185 | ```java
186 | // 也可以用asyncGroupRunner方法,每个参数的具体含义可以参考文档
187 | MagicDataProcessing.ConcurrentCollectionAsync().asyncGroupRunner(dataList, data -> {
188 |
189 | // 这里是每一组List
190 | for(String item : data){
191 | // 这里可以拿到List里的元素,进行处理
192 | System.out.println(data);
193 | }
194 |
195 | },
196 | 10, // 每组多少条元素
197 | 1, // 每组之间同步等待多久
198 | TimeUnit.MINUTES // 等待的时间单位
199 | )
200 | .start(); // 一样要调用start方法
201 | ```
202 |
203 | 同上
204 |
205 | ## 并发处理所有Map类的集合里的元素
206 |
207 | Map的逻辑跟Collection一模一样,只不过是传入的集合变成了Map,就不再累述了,感谢理解。
208 |
209 | ### 同步执行
210 |
211 | #### 每个元素并发执行
212 |
213 | ```java
214 | // 假如有一个Map需要并发处理里面的元素
215 | Map dataMap = new HashMap<>();
216 |
217 | // 只需要将他传入syncRunner方法即可
218 | MagicDataProcessing.getConcurrentMapSync()
219 | .syncRunner(dataMap, (key, value) -> {
220 |
221 | // 这里可以拿到Map里的元素,进行处理
222 | System.out.println(key);
223 | System.out.println(value);
224 |
225 | }, 10, 1, TimeUnit.MINUTES);
226 | ```
227 |
228 | #### 每一组并发执行
229 |
230 | ```java
231 | // 也可以用syncGroupRunner方法
232 | MagicDataProcessing.getConcurrentMapSync()
233 | .syncGroupRunner(dataMap, data -> {
234 |
235 | // 这里是每一组Map
236 | for(Map.Entry entry : data.entrySet()){
237 | // 这里可以拿到Map里的每一个元素
238 | System.out.println(entry.getKey());
239 | System.out.println(entry.getValue());
240 | }
241 |
242 | }, 10, 1, TimeUnit.MINUTES);
243 | ```
244 |
245 | ### 异步执行
246 |
247 | #### 每个元素并发执行
248 |
249 | ```java
250 | // 假如有一个Map需要并发处理里面的元素
251 | Map dataMap = new HashMap<>();
252 |
253 | // 只需要将他传入asyncRunner方法即可
254 | MagicDataProcessing.getConcurrentMapAsync().asyncRunner(dataMap, (key, value) -> {
255 |
256 | // 这里可以拿到Map里的元素,进行处理
257 | System.out.println(key);
258 | System.out.println(value);
259 |
260 | },
261 | 10,
262 | 1,
263 | TimeUnit.MINUTES
264 | )
265 | .start(); // 一样要调用start方法
266 | ```
267 |
268 | #### 每一组并发执行
269 |
270 | ```java
271 | // 也可以用asyncGroupRunner方法
272 | MagicDataProcessing.getConcurrentMapAsync().asyncGroupRunner(dataMap, data -> {
273 |
274 | // 这里是每一组Map
275 | for(Map.Entry entry : data.entrySet()){
276 | // 这里可以拿到Map里的每一个元素
277 | System.out.println(entry.getKey());
278 | System.out.println(entry.getValue());
279 | }
280 |
281 | },
282 | 10,
283 | 1,
284 | TimeUnit.MINUTES
285 | )
286 | .start(); // 一样要调用start方法;
287 | ```
288 |
289 | ## 生产者与消费者
290 |
291 | 这是一个多对多的模型,多个生产者可以给多个消费者推送不同类型的数据,
292 |
293 | ### 我们先创建一个生产者
294 | ```java
295 | public class DemoProducer extends MagicProducer {
296 |
297 | /**
298 | * 设置ID,必须全局唯一,默认是当前类的全名
299 | * 如果采用默认值,可以不重写这个方法
300 | * @return
301 | */
302 | @Override
303 | public String getId() {
304 | return super.getId();
305 | }
306 |
307 | /**
308 | * 设置producer方法是否重复执行,默认重复
309 | * 如果采用默认值,可以不重写这个方法
310 | * @return
311 | */
312 | @Override
313 | public boolean getLoop() {
314 | return super.getLoop();
315 | }
316 |
317 | /**
318 | * 设置 是否等消费者全部空闲了才继续生产下一轮数据,默认false
319 | * 如果采用默认值,可以不重写这个方法
320 | * @return
321 | */
322 | @Override
323 | public boolean getAllFree() {
324 | return super.getAllFree();
325 | }
326 |
327 | /**
328 | * 当生产者启动后,会自动执行这个方法,我们可以在这个方法里生产数据,并通过publish方法发布给消费者
329 | *
330 | * 这边举一个例子
331 | * 假如我们需要不断地扫描某张表,根据里面的数据状态去执行一些业务逻辑
332 | * 那么我们可以在这个方法里写一个查询的逻辑,然后将查询到数据发送给消费者
333 | */
334 | @Override
335 | public void producer() {
336 | // 根据上面的例子,我们可以查询这张表里符合条件的数据
337 | List