Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7dde6a2

Browse files
[docs update]补充几个工作流引擎开源项目
1 parent c800fc0 commit 7dde6a2

2 files changed

Lines changed: 26 additions & 76 deletions

File tree

‎docs/java/concurrent/java-concurrent-questions-03.md‎

Lines changed: 19 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -18,90 +18,33 @@ head:
1818

1919
### ThreadLocal 有什么用?
2020

21-
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。**如果想实现每一个线程都有自己的专属本地变量该如何解决呢?**
21+
通常情况下,我们创建的变量可以被任何一个线程访问和修改。这在多线程环境中可能导致数据竞争和线程安全问题。那么,**如果想让每个线程都有自己的专属本地变量,该如何实现呢?**
2222

23-
JDK 中自带的`ThreadLocal`类正是为了解决这样的问题。 **`ThreadLocal`类主要解决的就是让每个线程绑定自己的值,可以将`ThreadLocal`类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。**
23+
JDK 中提供的 `ThreadLocal` 类正是为了解决这个问题。**`ThreadLocal` 类允许每个线程绑定自己的值**,可以将其形象地比喻为一个"存放数据的盒子"。每个线程都有自己独立的盒子,用于存储私有数据,确保不同线程之间的数据互不干扰。
2424

25-
如果你创建了一个`ThreadLocal`变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是`ThreadLocal`变量名的由来。他们可以使用 `get()` `set()` 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
25+
当你创建一个 `ThreadLocal` 变量时,每个访问该变量的线程都会拥有一个独立的副本。这也是`ThreadLocal` 名称的由来。线程可以通过 `get()` 方法获取自己线程的本地副本,或通过 `set()` 方法修改该副本的值,从而避免了线程安全问题。
2626

27-
再举个简单的例子:两个人去宝屋收集宝物,这两个共用一个袋子的话肯定会产生争执,但是给他们两个人每个人分配一个袋子的话就不会出现这样的问题。如果把这两个人比作线程的话,那么 ThreadLocal 就是用来避免这两个线程竞争的。
28-
29-
### 如何使用 ThreadLocal?
30-
31-
相信看了上面的解释,大家已经搞懂 `ThreadLocal` 类是个什么东西了。下面简单演示一下如何在项目中实际使用 `ThreadLocal`
27+
举个简单的例子:假设有两个人去宝屋收集宝物。如果他们共用一个袋子,必然会产生争执;但如果每个人都有一个独立的袋子,就不会有这个问题。如果将这两个人比作线程,那么 `ThreadLocal` 就是用来避免这两个线程竞争同一个资源的方法。
3228

3329
```java
34-
import java.text.SimpleDateFormat;
35-
import java.util.Random;
36-
37-
public class ThreadLocalExample implements Runnable{
38-
39-
// SimpleDateFormat 不是线程安全的,所以每个线程都要有自己独立的副本
40-
private static final ThreadLocal<SimpleDateFormat> formatter = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd HHmm"));
41-
42-
public static void main(String[] args) throws InterruptedException {
43-
ThreadLocalExample obj = new ThreadLocalExample();
44-
for(int i=0 ; i<10; i++){
45-
Thread t = new Thread(obj, ""+i);
46-
Thread.sleep(new Random().nextInt(1000));
47-
t.start();
48-
}
49-
}
50-
51-
@Override
52-
public void run() {
53-
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
54-
try {
55-
Thread.sleep(new Random().nextInt(1000));
56-
} catch (InterruptedException e) {
57-
e.printStackTrace();
58-
}
59-
//formatter pattern is changed here by thread, but it won't reflect to other threads
60-
formatter.set(new SimpleDateFormat());
30+
public class ThreadLocalExample {
31+
private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
6132

62-
System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
33+
public static void main(String[] args) {
34+
Runnable task = () -> {
35+
int value = threadLocal.get();
36+
value += 1;
37+
threadLocal.set(value);
38+
System.out.println(Thread.currentThread().getName() + " Value: " + threadLocal.get());
39+
};
40+
41+
Thread thread1 = new Thread(task, "Thread-1");
42+
Thread thread2 = new Thread(task, "Thread-2");
43+
44+
thread1.start(); // 输出: Thread-1 Value: 1
45+
thread2.start(); // 输出: Thread-2 Value: 1
6346
}
64-
6547
}
66-
67-
```
68-
69-
输出结果 :
70-
71-
```plain
72-
Thread Name= 0 default Formatter = yyyyMMdd HHmm
73-
Thread Name= 0 formatter = yy-M-d ah:mm
74-
Thread Name= 1 default Formatter = yyyyMMdd HHmm
75-
Thread Name= 2 default Formatter = yyyyMMdd HHmm
76-
Thread Name= 1 formatter = yy-M-d ah:mm
77-
Thread Name= 3 default Formatter = yyyyMMdd HHmm
78-
Thread Name= 2 formatter = yy-M-d ah:mm
79-
Thread Name= 4 default Formatter = yyyyMMdd HHmm
80-
Thread Name= 3 formatter = yy-M-d ah:mm
81-
Thread Name= 4 formatter = yy-M-d ah:mm
82-
Thread Name= 5 default Formatter = yyyyMMdd HHmm
83-
Thread Name= 5 formatter = yy-M-d ah:mm
84-
Thread Name= 6 default Formatter = yyyyMMdd HHmm
85-
Thread Name= 6 formatter = yy-M-d ah:mm
86-
Thread Name= 7 default Formatter = yyyyMMdd HHmm
87-
Thread Name= 7 formatter = yy-M-d ah:mm
88-
Thread Name= 8 default Formatter = yyyyMMdd HHmm
89-
Thread Name= 9 default Formatter = yyyyMMdd HHmm
90-
Thread Name= 8 formatter = yy-M-d ah:mm
91-
Thread Name= 9 formatter = yy-M-d ah:mm
92-
```
93-
94-
从输出中可以看出,虽然 `Thread-0` 已经改变了 `formatter` 的值,但 `Thread-1` 默认格式化值与初始化值相同,其他线程也一样。
95-
96-
上面用于创建 `ThreadLocal` 变量的那段代码用到了 Java8 的知识,它等于下面这段代码,如果你写了下面这段代码的话,IDEA 会提示你转换为 Java8 的格式(IDEA 真的不错!)。因为 ThreadLocal 类在 Java 8 中扩展,使用一个新的方法`withInitial()`,将 Supplier 功能接口作为参数。
97-
98-
```java
99-
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
100-
@Override
101-
protected SimpleDateFormat initialValue(){
102-
return new SimpleDateFormat("yyyyMMdd HHmm");
103-
}
104-
};
10548
```
10649

10750
### ⭐️ThreadLocal 原理了解吗?

‎docs/open-source-project/system-design.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ icon: "xitongsheji"
128128
- [EasyScheduler](https://github.com/analysys/EasyScheduler "EasyScheduler") (已经更名为 DolphinScheduler,已经成为 Apache 孵化器项目):分布式易扩展的可视化工作流任务调度平台,主要解决"复杂任务依赖但无法直接监控任务健康状态"的问题。
129129
- [PowerJob](https://gitee.com/KFCFans/PowerJob):新一代分布式任务调度与计算框架,支持 CRON、API、固定频率、固定延迟等调度策略,提供工作流来编排任务解决依赖关系,使用简单,功能强大,文档齐全,欢迎各位接入使用!<http://www.powerjob.tech/>
130130

131+
## 工作流
132+
133+
1. [Flowable](https://github.com/flowable/flowable-engine) :Activiti5 的一个分支发展而来,功能丰富,在 Activiti 的基础上,引入了更多高级功能,如更强大的 CMMN(案例管理模型与符号)、DMN(决策模型与符号)支持,以及更灵活的集成选项。
134+
2. [Activiti](https://github.com/Activiti/Activiti):功能扩展相对保守,适合需要稳定 BPMN 2.0 工作流引擎的传统企业应用。
135+
3. [Warm-Flow](https://gitee.com/dromara/warm-flow):国产开源工作流引擎,其特点简洁轻量但又不简单,五脏俱全,组件独立,可扩展。
136+
4. [FlowLong](https://gitee.com/aizuda/flowlong):国产开源工作流引擎,专门中国特色流程审批打造。
137+
131138
## 分布式
132139

133140
### API 网关

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /