理解并行Java 8流产生的结果

Hac*_*amp 4 java-8 java-stream

每次运行并行流来读取文件并进行处理时,都不会得到相同的结果.

我有关于比萨饼的数据,并希望使用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;
    }

}
Run Code Online (Sandbox Code Playgroud)

//真实结果或预期结果(每个品种的数量)

蔬菜:5303非蔬菜:1786常规:1779中等:2660大:2650奶酪爆裂:3499普通奶酪爆裂:900便宜的奶酪爆裂:598

//运行-1结果

蔬菜比萨饼:5296非蔬菜比萨饼:1785普通:1779中等:2660大:2649奶酪爆炸比萨饼:3498普通奶酪爆裂:900便宜的奶酪爆裂:598 7060

//运行-2结果

蔬菜比萨饼:5294非蔬菜比萨饼:1786普通:1779中等:2659大:2648奶酪爆炸比萨饼:3497普通奶酪爆裂:900便宜的奶酪爆裂:598 7055

//运行3结果

蔬菜比萨饼:5303非蔬菜比萨饼:1786常规:1779中等:2660大:2650奶酪爆饼:3499普通奶酪爆裂:900便宜的奶酪爆裂:598 7086

我确实通过了这个链接.我无法将我的问题与该链接中发布的问题联系起来.我注意到如果我创建一个顺序流,我得到了预期的结果.任何领导都可能有所帮助.

Era*_*ran 6

你的updateCounts(String[] x)方法,通过所谓map的步骤Stream管道是不是线程安全的,并且它更新static变量.

因此,当多个线程同时调用它时,预计每次运行会产生不同的结果(即每次运行时static变量的最终值都不同).

Function传递到map不应该有副作用,在并行使用尤其不能时Stream.

使用Streams 进行此计算的更好方法:

  • 创建一个PizzaStatistics具有所有原始静态计数器变量作为实例变量的类.

  • updateCounts(应该重命名)将返回一个新PizzaStatistics实例,其中相关计数器设置为1.它不会更新任何静态变量.

  • Stream管道将使用终端操作reduce来生成PizzaStatistics包含总计的单个实例.

  • @HackChamp你可以使`updateCounts`方法同步,但它仍然是Streams的糟糕用法. (2认同)
  • @HackChamp你可以改变`updateCounts`来为它必须更新的每个变量调用一个不同的同步静态方法.这样`updateCounts`本身就不必同步了 (2认同)
  • @HackChamp以这种方式使用Stream管道仍然不是很好的做法,因为`map`不应该有副作用 (2认同)