Erastotenes Sieve in paraller programm Java

时间:2017-10-06 06:46:51

标签: java multithreading

我想制作一个使用Erastotenes Sieve计算素数的程序。在这个问题中,我想使用信号量在线程之间进行通信,以便在表格上进行数字计算。 到目前为止,我已经编写了类似的代码。

public static void main( String[] args ) throws InterruptedException {
        System.out.println("Podaj gorny zakres\n");
        Scanner scanner = new Scanner(System.in);
        Erastotenes erastotenes = new Erastotenes(Integer.parseInt(scanner.nextLine()));
        erastotenes.initializeTable();


        long start = System.nanoTime();

        List<SingleProcess.MyThread> list = new ArrayList<>();

        List<Integer> numbers = Dollar.$(2,erastotenes.getMaximumNumber()+1).toList();

        for(int i=0;i<2;i++)
        {
            list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
            list.get(list.size()-1).start();
            list.get(list.size()-1).join();
        }

        System.out.println(System.nanoTime() - start);

        //System.out.println("Liczba elementów: "+erastotenes.countPrimeElements());
    }

Erastotenes类。

public class Erastotenes {

    private int upperRange;
    private int maximumNumber;
    private int table[];

    public Erastotenes(int upperRange) {
        this.upperRange = upperRange;
        this.maximumNumber = (int)(Math.floor(Math.sqrt(upperRange)));
        this.table = new int[upperRange+1];
    }


    public int getMaximumNumber() {
        return maximumNumber;
    }

    public int getUpperRange() {
        return upperRange;
    }

    public void initializeTable()
    {
        for(int i=1;i<=upperRange;i++) {
            table[i] = i;
        }

    }

    public void makeSelectionOfGivenNumber(int number)
    {
        if (table[number] != 0) {
            int multiple;
            multiple = number+number;
            while (multiple<=upperRange) {
                table[multiple] = 0;
                multiple += number;
            }
        }
    }

    public List<Integer> getList()
    {
        List<Integer> list = Ints.asList(table);
        return  list.stream().filter(item->item.intValue()!=0 && item.intValue()!=1).collect(Collectors.toList());
    }
}

描述使用静态信号量进行计算的单个Thread的类看起来像这样。

public class SingleProcess {

    static Semaphore semaphore = new Semaphore(1);

    static class MyThread extends Thread {

        Erastotenes erastotenes;
        List<Integer> numbers;

        MyThread(Erastotenes erastotenes,List<Integer> numbers) {
            this.erastotenes = erastotenes;
            this.numbers=numbers;
        }


        public void run() {
            for(int number:numbers) {
                try {
                    semaphore.acquire();
                    //1System.out.println(number + " : got the permit!");
                    erastotenes.makeSelectionOfGivenNumber(number);

                } catch (InterruptedException e) {

                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }

        }

    }
}

我认为在半桌上分割数字从2到最大数字作为平方根,就像在这两个线程的erastotrenes算法中一样,会增加计算,但是如果upperRange为100000000,则paraller和sequence之间的差异不是那么大。我怎么能在另一个人中意识到Erastotenes Sieve的并行编程问题?

1 个答案:

答案 0 :(得分:2)

我认为你的主要问题是:

    for(int i=0;i<2;i++)
    {
        list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
        list.get(list.size()-1).start();
        list.get(list.size()-1).join();
    }

你开始一个线程,然后立即等待它完成;完全杀死了并行性。你可以在最后开始和等待:

    for(int i=0;i<2;i++)
    {
        list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
        list.get(list.size()-1).start();
    }
    for (Thread t : list) {
        t.join();
    }

但是,你的信号量tbh也存在问题。每个线程阻止所有其他线程做任何事情,只要它正在处理一个数字;这意味着所有的并行性都消失了。

你可以完全取消信号量IMO;将相同的索引设置为0几次并没有太大的危险,这就是在这个“关键部分”中发生的一切 - 但它根本不重要,因为没有人在所有线程完成之前读取有问题的数组值