Java 未为Runnable类型的类任务执行Run方法
我是多线程新手,在下面给出的示例中,我尝试将所有任务中的a和b的值求和,并将其保存在finalAnswer变量中。但不知何故,我的跑步方法没有被触发。请告诉我遗漏了什么。可能会有很多愚蠢的错误,但也要为此道歉Java 未为Runnable类型的类任务执行Run方法,java,multithreading,Java,Multithreading,我是多线程新手,在下面给出的示例中,我尝试将所有任务中的a和b的值求和,并将其保存在finalAnswer变量中。但不知何故,我的跑步方法没有被触发。请告诉我遗漏了什么。可能会有很多愚蠢的错误,但也要为此道歉 package MultiThreading; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concur
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());
}
}
包多线程;
导入java.util.LinkedList;
导入java.util.List;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公共类执行者{
静态列表=新建LinkedList();
公共静态void main(字符串[]args){
任务t1=新任务(1,2,“u1”);
任务t2=新任务(3,4,“u2”);
任务t3=新任务(5,6,“u3”);
任务t4=新任务(7,8,“u1”);
任务t5=新任务(9,10,“u2”);
任务t6=新任务(11,12,“u3”);
任务t7=新任务(13,14,“u1”);
任务t8=新任务(15,16,“u2”);
任务t9=新任务(17,18,“u3”);
列表。添加(t1);
增加(t2);
增加(t3);
列表。添加(t4);
列表。添加(t5);
列表。添加(t6);
增加(t7);
增加(t8);
增加(t8);
ExecutorService executor=Executors.newFixedThreadPool(5);
list.stream().forEach(x->executor.submit(()->新任务(x.a,x.b,x.userName));
System.out.println(“finalAnswer”+Task.finalAnswer);
}
静态类任务实现可运行{
INTA;
int b;
字符串用户名;
公共任务(int a、int b、字符串用户名){
这个a=a;
这个.b=b;
this.userName=用户名;
System.out.println(“a”+a+“b”+b+“用户名”+用户名);
}
静态整数finalAnswer=0;
@凌驾
公开募捐{
最终答案+=(a+b);
System.out.println(“线程信息”+Thread.currentThread().getName());
}
}
}
请建议。您可以在for循环中使用
executor.submit(task)
,这会触发任务在不同线程中运行。要查看它是否正在运行,您需要在主线程上等待,然后再使用thread.currentThread().join
或某种睡眠(someLongPeriod)打印finalAnswer
这样,在主线程等待时,单个任务在工作线程中运行。一旦执行完毕,您就可以打印finalAnswer了,您可以在for循环中使用
executor.submit(task)
,这会触发任务在不同的线程中运行。要查看它是否正在运行,您需要在主线程上等待,然后再使用thread.currentThread().join
或某种睡眠(someLongPeriod)打印finalAnswer
这样,在主线程等待时,单个任务在工作线程中运行。执行完毕后,您可以打印finalAnswer这一行:
list.stream().forEach(x -> executor.submit(() -> new Task(x.a, x.b, x.userName)));
不是我想你想的那样
这是提交一个runnable,它只是创建一个新任务。实际上:
list.stream().forEach(x -> executor.submit(new Runnable() {
@Override public void run() {
new Task(x.a, x.b, x.userName);
}
});
它实际上并不运行Task.run()
方法
因此,你可以:
- 直接调用
:run()
()->新任务(x.a、x.b、x.userName)。run()
- 提交
:新任务
执行者。提交(新任务(x.a、x.b、x.userName))
- 但是当
实现任务
:可运行
(或者使用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
但一般来说,executor框架的使用非常糟糕:最好向executor提交Callable
,并将所有结果累加到主线程中。这一行:
list.stream().forEach(x -> executor.submit(() -> new Task(x.a, x.b, x.userName)));
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
static AtomicInteger finalAnswer = new AtomicInteger(0) ;
static List<Task> list = new ArrayList<>();
public static void main(String[] args) {
list.add(new Task(1, 2, "u1"));
list.add(new Task(3, 4, "u2"));
list.add(new Task(5, 6, "u3"));
list.add(new Task(7, 8, "u1"));
list.add(new Task(9, 10, "u2"));
list.add(new Task(11, 12, "u3"));
list.add(new Task(13, 14, "u1"));
list.add(new Task(15, 16, "u2"));
list.add(new Task(17, 18, "u3"));
ExecutorService executor = Executors.newFixedThreadPool(5);
list.forEach(executor::submit);
executor.shutdown();
while (!executor.isTerminated()) {}
System.out.println(" finalAnswer " + Main.finalAnswer);
}
}
class Task implements Runnable {
int a;
int b;
String userName;
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);
}
@Override
public void run() {
Main.finalAnswer.getAndAdd(a + b);
System.out.println(" Thread info " + Thread.currentThread().getName());
}
}
不是我想你想的那样
这是提交一个runnable,它只是创建一个新任务。实际上:
list.stream().forEach(x -> executor.submit(new Runnable() {
@Override public void run() {
new Task(x.a, x.b, x.userName);
}
});
它实际上并不运行Task.run()
方法
因此,你可以:
- 直接调用
:run()
()->新任务(x.a、x.b、x.userName)。run()
- 提交
:新任务
执行者。提交(新任务(x.a、x.b、x.userName))
- 但是当
实现任务
:可运行
(或者使用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
但一般来说,executor框架的使用非常糟糕:最好向executor提交Callable
,并将所有结果累加到主线程中。导入java.util.ArrayList;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
static AtomicInteger finalAnswer = new AtomicInteger(0) ;
static List<Task> list = new ArrayList<>();
public static void main(String[] args) {
list.add(new Task(1, 2, "u1"));
list.add(new Task(3, 4, "u2"));
list.add(new Task(5, 6, "u3"));
list.add(new Task(7, 8, "u1"));
list.add(new Task(9, 10, "u2"));
list.add(new Task(11, 12, "u3"));
list.add(new Task(13, 14, "u1"));
list.add(new Task(15, 16, "u2"));
list.add(new Task(17, 18, "u3"));
ExecutorService executor = Executors.newFixedThreadPool(5);
list.forEach(executor::submit);
executor.shutdown();
while (!executor.isTerminated()) {}
System.out.println(" finalAnswer " + Main.finalAnswer);
}
}
class Task implements Runnable {
int a;
int b;
String userName;
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);
}
@Override
public void run() {
Main.finalAnswer.getAndAdd(a + b);
System.out.println(" Thread info " + Thread.currentThread().getName());
}
}
导入java.util.LinkedList;
导入java.util.List;
导入java.util.Map;
导入java.util.con