java - 没有为 Runnable 类型的类 Task 执行 Run 方法
问题描述
我是多线程的新手,在下面给出的情况下,我试图将所有任务中的 a 和 b 的值相加并将其保存在finalAnswer变量中。但不知何故,我的运行方法没有被触发。请让我知道缺少什么。可能有很多愚蠢的错误为同样的道歉。
package MultiThreading;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Executor {
static List<Task> list = new LinkedList<Task>();
public static void main(String[] args) {
Task t1 = new Task(1, 2, "u1");
Task t2 = new Task(3, 4, "u2");
Task t3 = new Task(5, 6, "u3");
Task t4 = new Task(7, 8, "u1");
Task t5 = new Task(9, 10, "u2");
Task t6 = new Task(11, 12, "u3");
Task t7 = new Task(13, 14, "u1");
Task t8 = new Task(15, 16, "u2");
Task t9 = new Task(17, 18, "u3");
list.add(t1);
list.add(t2);
list.add(t3);
list.add(t4);
list.add(t5);
list.add(t6);
list.add(t7);
list.add(t8);
list.add(t8);
ExecutorService executor = Executors.newFixedThreadPool(5);
list.stream().forEach(x -> executor.submit(() -> new Task(x.a, x.b, x.userName)));
System.out.println(" finalAnswer " + Task.finalAnswer);
}
static class Task implements Runnable {
int a;
int b;
String userName;
public Task(int a, int b, String userName) {
this.a = a;
this.b = b;
this.userName = userName;
System.out.println(" a " + a + " b " + b + " userName " + userName);
}
static Integer finalAnswer = 0;
@Override
public void run() {
finalAnswer += (a + b);
System.out.println(" Thread info " + Thread.currentThread().getName());
}
}
}
请,建议。
解决方案
这一行:
list.stream().forEach(x -> executor.submit(() -> new Task(x.a, x.b, x.userName)));
没有做我认为你认为的事情。
这是提交一个可运行的,它只是创建一个新任务。有效:
list.stream().forEach(x -> executor.submit(new Runnable() {
@Override public void run() {
new Task(x.a, x.b, x.userName);
}
});
它实际上并没有运行该Task.run()
方法。
所以,你可以:
- 直接调用
run()
:() -> new Task(x.a, x.b, x.userName).run()
- 提交
new Task
:executor.submit(new Task(x.a, x.b, x.userName))
- 但是,为什么要
Task
在Task
实现时创建 newRunnable
:(executor.submit(x)
或者更简单,使用list.forEach(executor::submit)
)。
但是,您会遇到finalAnswer
变量更新的原子性和可见性问题。
finalAnswer += (a + b);
不是原子的:它是finalAnswer = finalAnswer + (a + b)
. 没有什么能阻止另一个线程finalAnswer
在读取和写入之间写入。System.out.println(" finalAnswer " + Task.finalAnswer);
不保证看到 的更新值finalAnswer
。
最简单的解决方案是相互同步对finalAnswer
变量的访问:
synchronized (Task.class) {
System.out.println(" finalAnswer " + Task.finalAnswer);
}
//
synchronized (Task.class) {
finalAnswer += (a * b);
}
AtomicInteger
也存在其他解决方案,例如使用。
但总的来说,这是对执行器框架的一个非常糟糕的使用:最好是提交Callable<Integer>
给执行器,然后在主线程中将所有结果相加。
推荐阅读
- java - Java:ObjectMapper 在请求/响应后更改 Pojo 的值/结构
- r - 在 R 中的 highchart 中添加 x-label 空格
- node.js - 使用谷歌图表 API 和 node.js 设计一个 Web 界面来发送传感器数据
- c# - 将多个 CustomUserControl 模板组合成一个模板
- reactjs - 使用 react-pdf 处理未处理的拒绝(错误)获取 pdf 页面尺寸:传输被破坏
- javascript - 数据中的Vue.js调用方法
- node.js - client.login('TOKEN') 两次会导致问题吗?
- msgraph - 通过用户的加入 URL 获取 onlineMeeting
- mongodb - 没有从 MongoDB 收到重复的条目消息
- c++ - = 运算符导致内存丢失