Domanda

I must create simple application with threads. Task: faster calculation than serial processing. I must use methods notify() or notifyAll(), wait(), interrupt() and operator synchronized. I tried solve this by example from book. This example is typical producent consumer task. But parallel threads calculating is slower then serial.

Class with notify(), wait() and synchronized:

public class Reader {
  private boolean isRead = false;
  private boolean isFileEnd = false;
  private int value;
  private int[] pole;
  private int pocitadlo=0;

  public Reader(int[]pole) {
      this.pole=pole;
  }

  synchronized public void loadValue() {
    while (isRead == true) {
      try {
        wait();
      }
      catch (InterruptedException e) { }
    }


      if (pocitadlo<pole.length) {
        value = pole[pocitadlo];
        pocitadlo++;
      }
      else {
        isFileEnd = true;
        Thread.currentThread().interrupt();
      }

    isRead = true;
    notifyAll();
  }

  synchronized public int getValue() {
    while (isRead == false) {
      try {
        wait();
      }
      catch (InterruptedException e) { }
    }
    isRead = false;
    if (isFileEnd == false) {
      notifyAll();
      return value;
    }
    else {
      Thread.currentThread().interrupt();
      return 0;
    }
  }
}

Producer class:

public class Producent extends Thread {
    private Reader reader;

    public Producent(Reader reader) {
        this.reader = reader;
    }

    @Override
    public void run() {
        while (interrupted() == false) {
            reader.loadValue();
        }
    }
}

Consumer class:

public class Konzument extends Thread {
    private Reader reader;
    private double sum = 0;

    public Konzument(Reader reader) {
        this.reader = reader;
    }

    @Override
    public void run() {
        int number;
        while (true) {
            number = reader.getValue();
            if (interrupted() == false)
                sum += Math.sqrt(number);
            else
                break;
        }
    }

    public double getSum(){
        return sum;
    }
}

And main class code (I know that I can create objects in cycles for bigger comfort but this is only example):

public class PARPV2 {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    Watch watch=new Watch();
    double suma=0;    
        int size=1000000;
        int[]array1=new int[size];
        int[]array2=new int[size];
        int[]array3=new int[size];
        int[]array4=new int[size];
        int[]array5=new int[size];

        generate(array1);
        generate(array2);
        generate(array3);
        generate(array4);
        generate(array5);

        Reader reader1=new Reader(array1);
        Reader reader2=new Reader(array2);
        Reader reader3=new Reader(array3);
        Reader reader4=new Reader(array4);
        Reader reader5=new Reader(array5);

        Producent p1=new Producent(reader1);
        Konzument k1=new Konzument(reader1);
        Producent p2=new Producent(reader2);
        Konzument k2=new Konzument(reader2);
        Producent p3=new Producent(reader3);
        Konzument k3=new Konzument(reader3);
        Producent p4=new Producent(reader4);
        Konzument k4=new Konzument(reader4);
        Producent p5=new Producent(reader5);
        Konzument k5=new Konzument(reader5);

        watch.start();

        p1.start();
        k1.start();
        p2.start();
        k2.start();
        p3.start();
        k3.start();
        p4.start();
        k4.start();
        p5.start();
        k5.start();
    try {


        p1.join();
        k1.join();
        p2.join();
        k2.join();
        p3.join();
        k3.join();
        p4.join();
        k4.join();
        p5.join();
        k5.join();

        suma=k1.getSum()+k2.getSum()+k3.getSum()+k4.getSum()+k5.getSum();
        System.out.println("paralelne: "+watch.stop(false));
        System.out.println("suma: "+suma);
    } catch (InterruptedException ex) {
        Logger.getLogger(PARPV2.class.getName()).log(Level.SEVERE, null, ex);
    }
    double sum1=0;
    double sum2=0;
    double sum3=0;
    double sum4=0;
    double sum5=0;

    watch.start();

    for (int i = 0; i < array1.length; i++) {
        sum1+=Math.sqrt(array1[i]);
    }
    for (int i = 0; i < array2.length; i++) {
        sum2+=Math.sqrt(array2[i]);
    }
    for (int i = 0; i < array3.length; i++) {
        sum3+=Math.sqrt(array3[i]);
    }
    for (int i = 0; i < array4.length; i++) {
        sum4+=Math.sqrt(array4[i]);
    }
    for (int i = 0; i < array5.length; i++) {
        sum5+=Math.sqrt(array5[i]);
    }
    suma=sum1+sum2+sum3+sum4+sum5;
    System.out.println("serial: "+watch.stop(false));
    System.out.println("suma: "+suma);
}
public static void generate(int[]array){
    Random r=new Random();
    for (int i = 0; i < array.length; i++) {
        array[i]=r.nextInt(100);
    }
}

}

When I run this program, serial computing is much faster than parallel. But I have dual core and I thing that parallel calculation must be faster. I am not experienced in threads and maybe my example is dummy...Please, where can be a problem? Thanks

È stato utile?

Soluzione

If you want faster execution using Threads, I think that you should use a single class that will accomplish the same thing as serial, something like that :

public class Calc extends Thread {

    private int[] array;
    private double sum;

    public Calc(int[] array) {
        this.array = array;
        this.sum = 0;
    }

    @Override
    public void run() {
        for (int i = 0; i < array.length; i++) {
            sum += Math.sqrt(array[i]);
        }
    }

    public double getSum() {
        return this.sum;
    }
}

In this way, parallel computing is 2 times faster than serial coputing. I think the pattern Producer-Consummer you applied can't be faster than serial because you make way more instructions and breaks in the code by :

  1. Getting a new value (Consumer waits a new item to be available)
  2. Using this value (Producer waits consummer to finish its calculation)

Maybe the producer should be the one who generates random number, and the consummer the one using these values ?

(And please use while(isRead) and ! operator for the contrary instead of those ugly while(isRead == false) : this is more readable ;))

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top