簡體   English   中英

Java線程notify()wait()用於更快的計算

[英]Java threads notify() wait() for faster calculation

我必須使用線程創建簡單的應用程序。 任務:比串行處理更快的計算。 我必須使用方法notify( )或notifyAll()wait()interrupt()和操作符synchronized 我試圖通過書中的例子解決這個問題。 此示例是典型的生產消費者任務。 但是並行線程的計算要慢於串行線程。

具有notify()wait()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;
    }
  }
}

生產者類別:

public class Producent extends Thread {
    private Reader reader;

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

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

消費類:

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;
    }
}

和主類代碼(我知道我可以為更舒適地循環創建對象,但這僅是示例):

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);
    }
}

}

當我運行該程序時,串行計算比並行處理要快得多。 但是我有雙核,我認為並行計算必須更快。 我沒有線程方面的經驗,也許我的例子是虛擬的。。。請問哪里有問題? 謝謝

如果您想使用Threads更快地執行,我認為您應該使用一個單獨的類,該類將完成與Serial相同的操作,例如:

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;
    }
}

這樣,並行計算的速度是串行計算速度的2倍。 我認為您使用的Producer-Consummer模式不能比串行模式快,因為您可以通過以下方式使更多指令和代碼中斷:

  1. 獲取新值(消費者等待新商品可用)
  2. 使用此值(生產者等待消費者完成其計算)

也許生產者應該是生成隨機數的人,而消費者應該是使用這些值的人?

(並且請相反使用while(isRead)!運算符,而不要使用丑陋的while(isRead == false) :這更易讀;))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM