每次运行并行流以读取和处理文件时,都不会得到相同的结果。
我有关于披萨的数据,并且希望使用Map和全局变量来统计不同的变量。我应该只使用全局变量。但是,当我运行代码时,每次都会得到不同的结果。输入文件完全未修改。
package Assignment;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GlobalVariables {
static int vegPizzas = 0;
static int N_V_Pizzas = 0;
static int Size_regular = 0;
static int Size_medium = 0;
static int Size_large = 0;
static int Cheese_Burst = 0;
static int Cheese_regular = 0;
static int cheap_cheese = 0;
static Stream<String> reader;
static int rows = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
reader = Files.lines(Paths.get("data/SampleData.csv")).parallel();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
reader.map(x -> x.split(","))
.filter(x -> (!(x[0].equals("NULL") || x[1].equals("NULL") || x[2].equals("NULL") || x[3].equals("NULL"))))
.map(x -> updateCounts(x)).collect(Collectors.toList());
printResults();
System.out.println(rows);//to have a count of rows after filtering of NULL values is done
}
private static void printResults() {
// TODO Auto-generated method stub
System.out.println("veg pizzas: " + vegPizzas);
System.out.println("non veg pizzas: " + N_V_Pizzas);
System.out.println("regular: " + Size_regular + " medium: " + Size_medium + " large: " +Size_large);
System.out.println("cheese burst pizzas: " + Cheese_Burst);
System.out.println("regular cheese burst: " + Cheese_regular);
System.out.println("cheaper cheese burst: " + cheap_cheese);
}
private static Object updateCounts(String[] x) {
// TODO Auto-generated method stub
// static int vegPizzas = 0;
// static int N_V_Pizzas = 0;
// static int Size_regular = 0;
// static int Size_medium = 0;
// static int Size_large = 0;
// static int Cheese_Burst = 0;
// static int Cheese_regular = 0;
// static int cheap_cheese = 0;
rows++;
int flag_regular = 0;
if(x[9].equals("Y")) {
vegPizzas++;
}else if(x[9].equals("N")) {
N_V_Pizzas++;
}
if(x[6].equals("R")) {
Size_regular++;
flag_regular = 1;
}
else if(x[6].equals("M")) {
Size_medium++;
}
else if(x[6].equals("L")) {
Size_large++;
}
if(x[5].equals("Y")) {
Cheese_Burst++;
if(flag_regular == 1) {
Cheese_regular++;
}
if(Integer.parseInt(x[7]) < 500) {
cheap_cheese++;
}
}
return x;
}
}
//真实结果或预期结果(每个品种的计数)
蔬菜:5303 非蔬菜:1786年 常规:1779中:2660大:2650 起司爆裂:3499 常规奶酪爆裂:900 便宜的奶酪爆破:598//运行-1结果
素食披萨:5296 非素食披萨:1785年 常规:1779中:2660大:2649 奶酪碎披萨:3498 常规奶酪爆裂:900 便宜的奶酪爆裂:598 7060// Run-2结果
蔬菜比萨饼:5294 非素食披萨:1786年 常规:1779中:2659大:2648 奶酪爆裂比萨饼:3497 常规奶酪爆裂:900 便宜的奶酪爆裂:598 7055// Run-3结果
蔬菜比萨:5303 非素食披萨:1786年 常规:1779中:2660大:2650 奶酪爆裂比萨饼:3499 常规奶酪爆裂:900 便宜的奶酪爆裂:598 7086我确实经历了这个link。我无法将我的问题与该链接中发布的问题联系起来。我确实注意到,如果创建顺序流,我将获得预期的结果。任何线索都可能会有所帮助。
答案 0 :(得分:6)
由updateCounts(String[] x)
管道的map
步骤调用的Stream
方法不是线程安全的,它会更新static
变量。
因此,当多个线程同时调用它时,预计每次运行都会产生不同的结果(即static
变量的最终值在每次运行中都会不同)。
传递给Function
的{{1}}应该没有副作用,尤其是在并行map
中使用时。
使用Stream
s进行计算的更好方法:
创建一个Stream
类,将所有原始静态计数器变量作为实例变量。
PizzaStatistics
(应重命名)将返回一个新的updateCounts
实例,其中相关计数器设置为1。它不会更新任何静态变量。
Stream管道将使用终端操作PizzaStatistics
来生成包含总数的单个reduce
实例。