Java - 如何使这些方法成为多线程?

时间:2013-05-14 19:17:08

标签: java multithreading jvm

当前代码是单线程的。它从文件中读取数据,生成随机数并检查这些数字是否属于给定的间隔。

import java.io.*;
import java.util.*;

class Generator {
    private double mean;
    private double variance;
    private long amountOfNumbersToGenerate;

    public Generator(double mean, double variance, long amountOfNumbersToGenerate) {
        this.mean = mean;
        this.variance = variance;
        this.amountOfNumbersToGenerate = amountOfNumbersToGenerate;
    }

    double getMean() {
        return mean;
    }

    double getVariance() {
        return variance;
    }

    long getAmountOfNumbersToGenerate() {
        return amountOfNumbersToGenerate;
    }
}

class Interval {
    private double start;
    private double end;

    public Interval(double start, double end) {
        this.start = start;
        this.end = end;
    }

    double getStart() {
        return start;
    }

    double getEnd() {
        return end;
    }
}

class ParsedData {
    private Vector<Generator> generators;
    private Vector<Interval> intervals;

    public ParsedData(Vector<Generator> generators, Vector<Interval> intervals) {
        this.generators = generators;
        this.intervals = intervals;
    }

    Vector<Generator> getGenerators() {
        return generators;
    }

    Vector<Interval> getIntervals() {
        return intervals;
    }
}

class Worker extends Thread {

    public Worker() {

    }

}

class Start {
    static ParsedData readDataFromFile(String path) throws IOException {
        File file = new File(path);
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        line = br.readLine();
        String delimiter = "\\s+";

        // generators
        long generatorSize =  Long.parseLong(line);
        Vector<Generator> generators = new Vector<Generator>();
        for(long i =0; i < generatorSize; i++) {
            line = br.readLine();

            Scanner f = new Scanner(line);
            f.useLocale(Locale.US); //without this line the program wouldn't work on machines with different locales
            f.useDelimiter(delimiter);

            Generator g = new Generator(f.nextDouble(), f.nextDouble(), f.nextInt());
            generators.add(g);
        }

        line = br.readLine();
        long intervalSize = Long.parseLong(line);
        Vector<Interval> intervals = new Vector<Interval>();
        for(long i = 0; i < intervalSize; i++) {
            line = br.readLine();
            System.out.println(line);

            Scanner f = new Scanner(line);
            f.useLocale(Locale.US); //without this line the program wouldn't work on machines with different locales
            f.useDelimiter(delimiter);

            Interval interval = new Interval(f.nextDouble(), f.nextDouble());
            intervals.add(interval);
        }
        br.close();

        return new ParsedData(generators, intervals);
    }

    static double boxMullerMarsagliaPolarRand(double mean, double variance) {
        double micro = mean;
        double sigma = Math.sqrt(variance);
        double y, x, omega;
        Random random = new Random();

        do {
            x = random.nextDouble();
            y = random.nextDouble();
            omega = x * x + y * y;
        } while (!(0.0 < omega && omega < 1.0));
        double sigma_sqrt = sigma * Math.sqrt(-2.0 * Math.log(omega) / omega);
        double g = micro + x * sigma_sqrt;
        // float h = micro + y * sigma_sqrt;
        return g;
    }

    /////////////////////////////////////////
    // TODO: refactor code into multithreaded
    static Vector<Double> generateRandomNumbers(ParsedData parsedData) {
        Vector<Double> generatedNumbers = new Vector<Double>();

        for(int i = 0; i < parsedData.getGenerators().size(); i++) {
            Generator g = parsedData.getGenerators().get(i);
            for(long j = 0; j < g.getAmountOfNumbersToGenerate(); j++) {
                double random = boxMullerMarsagliaPolarRand(g.getMean(), g.getVariance());
                generatedNumbers.add(random);
            }
        }
        return generatedNumbers;
    }

    /////////////////////////////////////////
    // TODO: refactor code into multithreaded
    static int[] checkIntervals(ParsedData parsedData, Vector<Double> generatedNumbers) {
        int[] numberOfHits = new int[parsedData.getIntervals().size()];
        for(int j = 0; j < parsedData.getIntervals().size(); j++) {
            Interval interval = parsedData.getIntervals().get(j);
            for(int i = 0; i < generatedNumbers.size(); i++) {
                if (interval.getStart() < generatedNumbers.get(i) && generatedNumbers.get(i) < interval.getEnd()) {
                    numberOfHits[j]++;
                }
            }
        }
        return numberOfHits;
    }

    public static void main(String args[]) {
        int amountOfThreads = Integer.parseInt(args[0]);
        String path = System.getProperty("user.dir") + "/input.dat";
        ParsedData parsedData = null;

        try {
            parsedData = readDataFromFile(path);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(parsedData.getGenerators().size());
        System.out.println(parsedData.getIntervals().size());

        Vector<Double> generatedNumbers = generateRandomNumbers(parsedData);

        int[] numberOfHits = checkIntervals(parsedData, generatedNumbers);

        for (int i = 0; i < numberOfHits.length; i++) {
            Interval interval = parsedData.getIntervals().get(i);
            System.out.println("" + (i+1) + " " + interval.getStart() + " " + interval.getEnd() + " " + numberOfHits[i]);
        }

        System.out.println(generatedNumbers.size());
    }
}

我不希望任何人为我编写/重构代码。

但我不知道如何使这个方法多线程:

   /////////////////////////////////////////
    // TODO: refactor code into multithreaded
    static Vector<Double> generateRandomNumbers(ParsedData parsedData) {
        Vector<Double> generatedNumbers = new Vector<Double>();

        for(int i = 0; i < parsedData.getGenerators().size(); i++) {
            Generator g = parsedData.getGenerators().get(i);
            for(long j = 0; j < g.getAmountOfNumbersToGenerate(); j++) {
                double random = boxMullerMarsagliaPolarRand(g.getMean(), g.getVariance());
                generatedNumbers.add(random);
            }
        }
        return generatedNumbers;
    }

    /////////////////////////////////////////
    // TODO: refactor code into multithreaded
    static int[] checkIntervals(ParsedData parsedData, Vector<Double> generatedNumbers) {
        int[] numberOfHits = new int[parsedData.getIntervals().size()];
        for(int j = 0; j < parsedData.getIntervals().size(); j++) {
            Interval interval = parsedData.getIntervals().get(j);
            for(int i = 0; i < generatedNumbers.size(); i++) {
                if (interval.getStart() < generatedNumbers.get(i) && generatedNumbers.get(i) < interval.getEnd()) {
                    numberOfHits[j]++;
                }
            }
        }
        return numberOfHits;
    }

2 个答案:

答案 0 :(得分:3)

制作此多线程的最简单方法是使用producer-consumer pattern,一个生产者读取数据并将其发送到BlockingQueue,消费者从BlockingQueue读取数据(使用take)并使用两种静态方法处理它。这样你就需要进行最小的重构 - 静态方法已经是可重入/线程安全的(假设不共享VectorParsedData参数),所以它们不需要完全修改。

答案 1 :(得分:2)

for循环简单地遍历输入,并且不依赖于先前的迭代。将循环的工作分开,并将每个任务分配给一个线程,然后组合线程输出。例如,一个线程迭代0 to i/2而另一个线程迭代i/2+1 to i

您需要了解线程:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html

为了管理线程及其返回值,我强烈建议使用ExecutorServiceFuture设计模式。以下是一些API文档:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html