Java多线程ForkJoinPool实例详解

时间:2022-09-23 08:13:46

引言

java 7提供了另外一个很有用的线程池框架,Fork/Join框架

理论

Fork/Join框架主要有以下两个类组成.

* ForkJoinPool 这个类实现了ExecutorService接口和工作窃取算法(Work-Stealing Algorithm).它管理工作者线程,并提供任务的状态信息,以及任务的执行信息

* ForkJoinTask 这个类是一个将在ForkJoinPool执行的任务的基类.

Fork/Join框架提供了在一个任务里执行fork()和join()操作的机制和控制任务状态的方法.通常,为了实现Fork/Join任务,需要实现一个以下两个类之一的子类

* RecursiveAction 用于任务没有返回值的场景

* RecursiveTask 用于任务有返回值的场景.

例子 先定个小目标,1亿就太多,先赚个一百万吧

现在你是一个深圳片区的某公司高级销售主管.现在定了一个目标,就是要赚个一百,让你一个人去赚,肯定有难度的.好在有一般手下,把目标缩小,让小弟们去赚,我们坐等拿钱.ok,开始编程

首先我们要定义个赚钱任务 MakeMoneyTask,如果要赚钱的目标小于最小目标,比如十万,那么就自己去完成,否则,就把任务分给小弟们去做.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class MakeMoneyTask extends RecursiveTask<Integer>{
  private static final int MIN_GOAL_MONEY = 100000;
  private int goalMoney;
  private String name;
  private static final AtomicLong employeeNo = new AtomicLong();
  public MakeMoneyTask(int goalMoney){
    this.goalMoney = goalMoney;
    this.name = "员工" + employeeNo.getAndIncrement() + "号";
  }
  @Override
  protected Integer compute() {
    if (this.goalMoney < MIN_GOAL_MONEY){
      System.out.println(name + ": 老板交代了,要赚 " + goalMoney + " 元,为了买车买房,加油吧....");
      return makeMoney();
    }else{
      int subThreadCount = ThreadLocalRandom.current().nextInt(10) + 2;
      System.out.println(name + ": 上级要我赚 " + goalMoney + ", 有点小多,没事让我" + subThreadCount + "个手下去完成吧," +
          "每人赚个 " + Math.ceil(goalMoney * 1.0 / subThreadCount) + "元应该没问题...");
      List<MakeMoneyTask> tasks = new ArrayList<>();
      for (int i = 0; i < subThreadCount; i ++){
        tasks.add(new MakeMoneyTask(goalMoney / subThreadCount));
      }
      Collection<MakeMoneyTask> makeMoneyTasks = invokeAll(tasks);
      int sum = 0;
      for (MakeMoneyTask moneyTask : makeMoneyTasks){
        try {
          sum += moneyTask.get();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
      System.out.println(name + ": 嗯,不错,效率还可以,终于赚到 " + sum + "元,赶紧邀功去....");
      return sum;
    }
  }
  private Integer makeMoney(){
    int sum = 0;
    int day = 1;
    try {
      while (true){
        Thread.sleep(ThreadLocalRandom.current().nextInt(500));
        int money = ThreadLocalRandom.current().nextInt(MIN_GOAL_MONEY / 3);
        System.out.println(name + ": 在第 " + (day ++) + " 天赚了" + money);
        sum += money;
        if (sum >= goalMoney){
          System.out.println(name + ": 终于赚到 " + sum + " 元, 可以交差了...");
          break;
        }
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return sum;
  }
}

最后我们写一个测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestMain {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    ForkJoinPool pool = new ForkJoinPool();
    ForkJoinTask<Integer> task = pool.submit(new MakeMoneyTask(1000000));
    do {
      try {
        TimeUnit.MILLISECONDS.sleep(5);
      }catch (InterruptedException e){
        e.printStackTrace();
      }
    }while (!task.isDone());
    pool.shutdown();
    System.out.println(task.get());
  }
}

运作之后结果如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
员工0号: 上级要我赚 1000000, 有点小多,没事让我10个手下去完成吧,每人赚个 100000.0元应该没问题…
员工1号: 上级要我赚 100000, 有点小多,没事让我7个手下去完成吧,每人赚个 14286.0元应该没问题…
员工11号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工10号: 上级要我赚 100000, 有点小多,没事让我5个手下去完成吧,每人赚个 20000.0元应该没问题…
员工18号: 老板交代了,要赚 20000 元,为了买车买房,加油吧….
员工9号: 上级要我赚 100000, 有点小多,没事让我3个手下去完成吧,每人赚个 33334.0元应该没问题…
员工23号: 老板交代了,要赚 33333 元,为了买车买房,加油吧….
员工22号: 老板交代了,要赚 20000 元,为了买车买房,加油吧….
员工22号: 在第 1 天赚了31432
员工22号: 终于赚到 31432 元, 可以交差了…
员工21号: 老板交代了,要赚 20000 元,为了买车买房,加油吧….
员工18号: 在第 1 天赚了32005
员工18号: 终于赚到 32005 元, 可以交差了…
员工19号: 老板交代了,要赚 20000 元,为了买车买房,加油吧….
员工23号: 在第 1 天赚了6166
员工21号: 在第 1 天赚了15433
员工19号: 在第 1 天赚了23419
员工19号: 终于赚到 23419 元, 可以交差了…
员工20号: 老板交代了,要赚 20000 元,为了买车买房,加油吧….
员工20号: 在第 1 天赚了10376
员工11号: 在第 1 天赚了11808
员工21号: 在第 2 天赚了31059
员工21号: 终于赚到 46492 元, 可以交差了…
员工8号: 上级要我赚 100000, 有点小多,没事让我4个手下去完成吧,每人赚个 25000.0元应该没问题…
员工26号: 老板交代了,要赚 25000 元,为了买车买房,加油吧….
员工11号: 在第 2 天赚了11902
员工11号: 终于赚到 23710 元, 可以交差了…
员工12号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工23号: 在第 2 天赚了9077
员工20号: 在第 2 天赚了30386
员工20号: 终于赚到 40762 元, 可以交差了…
员工10号: 嗯,不错,效率还可以,终于赚到 174110元,赶紧邀功去….
员工7号: 上级要我赚 100000, 有点小多,没事让我10个手下去完成吧,每人赚个 10000.0元应该没问题…
员工30号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工12号: 在第 1 天赚了31271
员工12号: 终于赚到 31271 元, 可以交差了…
员工26号: 在第 1 天赚了11631
员工13号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工26号: 在第 2 天赚了10160
员工30号: 在第 1 天赚了10786
员工30号: 终于赚到 10786 元, 可以交差了…
员工31号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工31号: 在第 1 天赚了15201
员工31号: 终于赚到 15201 元, 可以交差了…
员工32号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工26号: 在第 3 天赚了32642
员工26号: 终于赚到 54433 元, 可以交差了…
员工27号: 老板交代了,要赚 25000 元,为了买车买房,加油吧….
员工23号: 在第 3 天赚了33072
员工23号: 终于赚到 48315 元, 可以交差了…
员工24号: 老板交代了,要赚 33333 元,为了买车买房,加油吧….
员工24号: 在第 1 天赚了26309
员工24号: 在第 2 天赚了15420
员工24号: 终于赚到 41729 元, 可以交差了…
员工25号: 老板交代了,要赚 33333 元,为了买车买房,加油吧….
员工13号: 在第 1 天赚了33266
员工13号: 终于赚到 33266 元, 可以交差了…
员工14号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工25号: 在第 1 天赚了19270
员工25号: 在第 2 天赚了15842
员工25号: 终于赚到 35112 元, 可以交差了…
员工9号: 嗯,不错,效率还可以,终于赚到 125156元,赶紧邀功去….
员工6号: 上级要我赚 100000, 有点小多,没事让我9个手下去完成吧,每人赚个 11112.0元应该没问题…
员工40号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工32号: 在第 1 天赚了8133
员工32号: 在第 2 天赚了3518
员工32号: 终于赚到 11651 元, 可以交差了…
员工33号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工27号: 在第 1 天赚了23200
员工14号: 在第 1 天赚了6366
员工27号: 在第 2 天赚了10406
员工27号: 终于赚到 33606 元, 可以交差了…
员工28号: 老板交代了,要赚 25000 元,为了买车买房,加油吧….
员工40号: 在第 1 天赚了28078
员工40号: 终于赚到 28078 元, 可以交差了…
员工41号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工41号: 在第 1 天赚了12996
员工41号: 终于赚到 12996 元, 可以交差了…
员工42号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工33号: 在第 1 天赚了29188
员工33号: 终于赚到 29188 元, 可以交差了…
员工34号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工14号: 在第 2 天赚了17712
员工14号: 终于赚到 24078 元, 可以交差了…
员工15号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工28号: 在第 1 天赚了18623
员工28号: 在第 2 天赚了8205
员工28号: 终于赚到 26828 元, 可以交差了…
员工29号: 老板交代了,要赚 25000 元,为了买车买房,加油吧….
员工34号: 在第 1 天赚了30779
员工34号: 终于赚到 30779 元, 可以交差了…
员工35号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工42号: 在第 1 天赚了26164
员工42号: 终于赚到 26164 元, 可以交差了…
员工43号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工43号: 在第 1 天赚了2995
员工29号: 在第 1 天赚了347
员工15号: 在第 1 天赚了33056
员工15号: 终于赚到 33056 元, 可以交差了…
员工16号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工35号: 在第 1 天赚了3639
员工29号: 在第 2 天赚了22909
员工43号: 在第 2 天赚了2289
员工16号: 在第 1 天赚了27836
员工16号: 终于赚到 27836 元, 可以交差了…
员工17号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工43号: 在第 3 天赚了694
员工17号: 在第 1 天赚了16361
员工17号: 终于赚到 16361 元, 可以交差了…
员工1号: 嗯,不错,效率还可以,终于赚到 189578元,赶紧邀功去….
员工2号: 上级要我赚 100000, 有点小多,没事让我2个手下去完成吧,每人赚个 50000.0元应该没问题…
员工49号: 老板交代了,要赚 50000 元,为了买车买房,加油吧….
员工49号: 在第 1 天赚了8599
员工43号: 在第 4 天赚了10008
员工43号: 终于赚到 15986 元, 可以交差了…
员工44号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工29号: 在第 3 天赚了31298
员工29号: 终于赚到 54554 元, 可以交差了…
员工8号: 嗯,不错,效率还可以,终于赚到 169421元,赶紧邀功去….
员工39号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工49号: 在第 2 天赚了8099
员工35号: 在第 2 天赚了164
员工49号: 在第 3 天赚了5518
员工49号: 在第 4 天赚了22441
员工44号: 在第 1 天赚了6091
员工39号: 在第 1 天赚了18813
员工39号: 终于赚到 18813 元, 可以交差了…
员工48号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工44号: 在第 2 天赚了22324
员工44号: 终于赚到 28415 元, 可以交差了…
员工45号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工49号: 在第 5 天赚了28438
员工49号: 终于赚到 73095 元, 可以交差了…
员工50号: 老板交代了,要赚 50000 元,为了买车买房,加油吧….
员工35号: 在第 3 天赚了31797
员工35号: 终于赚到 35600 元, 可以交差了…
员工36号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工50号: 在第 1 天赚了18071
员工45号: 在第 1 天赚了22528
员工45号: 终于赚到 22528 元, 可以交差了…
员工46号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工36号: 在第 1 天赚了26828
员工36号: 终于赚到 26828 元, 可以交差了…
员工37号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工50号: 在第 2 天赚了32422
员工50号: 终于赚到 50493 元, 可以交差了…
员工2号: 嗯,不错,效率还可以,终于赚到 123588元,赶紧邀功去….
员工3号: 上级要我赚 100000, 有点小多,没事让我9个手下去完成吧,每人赚个 11112.0元应该没问题…
员工51号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工46号: 在第 1 天赚了1537
员工46号: 在第 2 天赚了27529
员工46号: 终于赚到 29066 元, 可以交差了…
员工47号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工48号: 在第 1 天赚了24791
员工48号: 终于赚到 24791 元, 可以交差了…
员工38号: 老板交代了,要赚 10000 元,为了买车买房,加油吧….
员工37号: 在第 1 天赚了17587
员工37号: 终于赚到 17587 元, 可以交差了…
员工47号: 在第 1 天赚了23693
员工47号: 终于赚到 23693 元, 可以交差了…
员工6号: 嗯,不错,效率还可以,终于赚到 211717元,赶紧邀功去….
员工5号: 上级要我赚 100000, 有点小多,没事让我7个手下去完成吧,每人赚个 14286.0元应该没问题…
员工60号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工51号: 在第 1 天赚了27189
员工51号: 终于赚到 27189 元, 可以交差了…
员工52号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工38号: 在第 1 天赚了32285
员工38号: 终于赚到 32285 元, 可以交差了…
员工66号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工7号: 嗯,不错,效率还可以,终于赚到 228718元,赶紧邀功去….
员工65号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工65号: 在第 1 天赚了26122
员工65号: 终于赚到 26122 元, 可以交差了…
员工64号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工52号: 在第 1 天赚了19239
员工52号: 终于赚到 19239 元, 可以交差了…
员工53号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工60号: 在第 1 天赚了10433
员工66号: 在第 1 天赚了25993
员工66号: 终于赚到 25993 元, 可以交差了…
员工63号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工60号: 在第 2 天赚了19529
员工60号: 终于赚到 29962 元, 可以交差了…
员工61号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工64号: 在第 1 天赚了6894
员工53号: 在第 1 天赚了13114
员工53号: 终于赚到 13114 元, 可以交差了…
员工54号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工54号: 在第 1 天赚了8237
员工61号: 在第 1 天赚了15878
员工61号: 终于赚到 15878 元, 可以交差了…
员工62号: 老板交代了,要赚 14285 元,为了买车买房,加油吧….
员工63号: 在第 1 天赚了32108
员工63号: 终于赚到 32108 元, 可以交差了…
员工4号: 上级要我赚 100000, 有点小多,没事让我9个手下去完成吧,每人赚个 11112.0元应该没问题…
员工67号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工64号: 在第 2 天赚了30531
员工64号: 终于赚到 37425 元, 可以交差了…
员工75号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工54号: 在第 2 天赚了13562
员工54号: 终于赚到 21799 元, 可以交差了…
员工55号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工55号: 在第 1 天赚了17774
员工55号: 终于赚到 17774 元, 可以交差了…
员工56号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工67号: 在第 1 天赚了24463
员工67号: 终于赚到 24463 元, 可以交差了…
员工68号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工56号: 在第 1 天赚了1677
员工62号: 在第 1 天赚了14266
员工75号: 在第 1 天赚了26532
员工75号: 终于赚到 26532 元, 可以交差了…
员工74号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工68号: 在第 1 天赚了32639
员工68号: 终于赚到 32639 元, 可以交差了…
员工69号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工69号: 在第 1 天赚了9513
员工56号: 在第 2 天赚了9154
员工56号: 在第 3 天赚了289
员工56号: 终于赚到 11120 元, 可以交差了…
员工57号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工62号: 在第 2 天赚了17321
员工62号: 终于赚到 31587 元, 可以交差了…
员工5号: 嗯,不错,效率还可以,终于赚到 199075元,赶紧邀功去….
员工59号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工69号: 在第 2 天赚了17971
员工69号: 终于赚到 27484 元, 可以交差了…
员工70号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工74号: 在第 1 天赚了26270
员工74号: 终于赚到 26270 元, 可以交差了…
员工73号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工70号: 在第 1 天赚了21237
员工70号: 终于赚到 21237 元, 可以交差了…
员工71号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工59号: 在第 1 天赚了4411
员工57号: 在第 1 天赚了3546
员工57号: 在第 2 天赚了29330
员工57号: 终于赚到 32876 元, 可以交差了…
员工58号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工73号: 在第 1 天赚了10674
员工71号: 在第 1 天赚了8821
员工59号: 在第 2 天赚了11887
员工59号: 终于赚到 16298 元, 可以交差了…
员工72号: 老板交代了,要赚 11111 元,为了买车买房,加油吧….
员工58号: 在第 1 天赚了28241
员工58号: 终于赚到 28241 元, 可以交差了…
员工3号: 嗯,不错,效率还可以,终于赚到 187650元,赶紧邀功去….
员工72号: 在第 1 天赚了14371
员工72号: 终于赚到 14371 元, 可以交差了…
员工73号: 在第 2 天赚了14918
员工73号: 终于赚到 25592 元, 可以交差了…
员工71号: 在第 2 天赚了28814
员工71号: 终于赚到 37635 元, 可以交差了…
员工4号: 嗯,不错,效率还可以,终于赚到 236223元,赶紧邀功去….
员工0号: 嗯,不错,效率还可以,终于赚到 1845236元,赶紧邀功去….
1845236

看到没有,员工0号把任务一百万直接分给了10个手下去做,每个手下有继续往下分,最终在七十几号人的努力下,终于完成了目标–一百万.而且还超出八十多万,老板一开心,直接把八十多万分给这七十多个员工分红了.

后记

通过上面这个例子的学习,相信应该很多人都可以掌握ForkJoinPool这个类,它的核心就是要完成某一个目标任务,如果目标任务太大,那么就创建多个子任务.然后一直等待这些子任务完成.最终完成之前定下的目标任务.

总结

以上就是本文关于Java多线程ForkJoinPool实例详解的全部内容,希望对大家有所帮助。欢迎各位参阅本站其他专题,有什么问题可以随时留言,小编会及时回复大家的。

原文链接:http://blog.csdn.net/tianshi_kco/article/details/53026192#comments