Threads Zwei Threads, aber doppelte Ausgabe verhindern (synchronized)

X

Xyz1

Gast
Mir wurde ein Programm zugesendet und meine Frage wär jetzt, wie ich die doppelte Ausgabe verhindere...

Java:
import java.util.Arrays;
import java.util.Scanner;

public class Unittest {
  private static Scanner s1;
  private static String p1, p2;

  public static void main(String[] args) {
    s1 = new Scanner(System.in);
    System.out.println("Adresse 1: ");
    p1 = s1.nextLine();
    System.out.println("Adresse 2: ");
    p2 = s1.nextLine();
    byte[] ip1 = ipv4ToBytes(p1);
    byte[] ip2 = ipv4ToBytes(p2);

    // Thread
    Runnable r1 = new Runnable() {
      @Override
      public void run() {
        byte[] a = ip1;
        while (true) {
          String s = bytesToIpv4(a);
          System.out.println("Die Adresse Thread 1 ist " + s);
          synchronized (s1) {
            if (isNotEquals(a, ip2)) {
              count(a);
            } else {
              break;
            }
          }
        }
      }
    };
    Runnable r2 = new Runnable() {
      @Override
      public void run() {
        byte[] a = ip2;
        while (true) {
          String s = bytesToIpv4(a);
          System.out.println("Die Adresse Thread 2 ist " + s);
          synchronized (s1) {
            if (isNotEquals(a, ip1)) {
              count2(a);
            } else {
              break;
            }
          }
        }
      }
    };

    new Thread(r1).start();
    new Thread(r2).start();
  }

  public static boolean isNotEquals(byte[] a, byte[] b) {
    return !Arrays.equals(a, b);
  }

  public static byte[] ipv4ToBytes(String ip) {
    String[] parts = ip.split("\\.");
    byte[] result = new byte[4];

    for (int i = 0; i < result.length; i++) {

      result[i] = (byte) Integer.parseInt(parts[i]);
    }
    return result;
  }

  public static void count(byte[] value) {

    int i = value.length;

    do {

      i--;
      value[i]++;
    } while (value[i] == 0);
  }

  public static void count2(byte[] value) {

    int i = value.length;

    do {

      i--;
      value[i]--;
    } while ((value[i] & 0xFF) == 255);
  }

  public static String bytesToIpv4(byte[] value) {

    return String.format("%d.%d.%d.%d", value[0] & 0xff, value[1] & 0xff, value[2] & 0xff, value[3] & 0xff);
  }

}


Code:
Adresse 1: 
255.255.254.240
Adresse 2: 
255.255.255.5
Die Adresse Thread 1 ist 255.255.254.240
Die Adresse Thread 2 ist 255.255.255.5
Die Adresse Thread 2 ist 255.255.255.4
Die Adresse Thread 1 ist 255.255.254.241
Die Adresse Thread 2 ist 255.255.255.3
Die Adresse Thread 1 ist 255.255.254.242
Die Adresse Thread 2 ist 255.255.255.2
Die Adresse Thread 1 ist 255.255.254.243
Die Adresse Thread 2 ist 255.255.255.1
Die Adresse Thread 2 ist 255.255.255.0
Die Adresse Thread 2 ist 255.255.254.255
Die Adresse Thread 2 ist 255.255.254.254
Die Adresse Thread 2 ist 255.255.254.253
Die Adresse Thread 2 ist 255.255.254.252
Die Adresse Thread 2 ist 255.255.254.251
Die Adresse Thread 2 ist 255.255.254.250
Die Adresse Thread 2 ist 255.255.254.249
Die Adresse Thread 2 ist 255.255.254.248
Die Adresse Thread 2 ist 255.255.254.247
Die Adresse Thread 1 ist 255.255.254.244
Die Adresse Thread 1 ist 255.255.254.245
Die Adresse Thread 1 ist 255.255.254.246
Die Adresse Thread 2 ist 255.255.254.246


Zusatzfrage: Wird das Programm immer anhalten? (bitte begründen)
 

Blender3D

Top Contributor
Der Code ist mit Fehlern behaftet.
z.B.
Java:
public static void count2(byte[] value) {
    int i = value.length;
    do {
      i--;
      value[i]--;
    } while ((value[i] & 0xFF) == 255);
  }

Die while Schleife macht hier keinen Sinn, da die Bedingung maximal 1 mal erfüllt sein kann. Wenn value[i] i == 256 --> value[i]-- --> value[i] -- --> Bedinung nicht mehr erfüllt.
Da der Name der Funktion count2 nicht aussagekräftig ist, kann man hier nur vermuten was die Funktion eigentlich machen soll.
Meine Annahme ist: Sie soll eine IP4 Adresse um eine Stelle herunterzählen.
Eine Andere Frage an dieser Stelle:
Java:
       synchronized (s1) {
            if (isNotEquals(a, ip1)) {
              count2(a);
            } else {
              break;
            }
s1 ist der Scanner der zum Einlesen der ip4 Strings dient. Warum wird eine Variable synchronisiert, auf die gar nicht mehr zugegriffen wird?
Zusatzfrage: Wird das Programm immer anhalten? (bitte begründen)
Da die Bedingung zum Abbruch des jeweiligen Threads die Gleichheit beider IP4 Adressen ist . Die Countfunktion aber immer nur die Letzte Stelle herauf oder herunter zählt --- > Nein es wird nicht immer abgebrochen.

Hier ein andere Variante.

Java:
public class Unittest {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Gib 2 IP4 Adressen ein:\nIP1 wird hinauf- und IP2 wird heruntergezählt.\n");
        System.out.println(
                "Die zählenden Threads stoppen wenn:\na) Beide die selbe IP Adresse haben.\nb) Die Limits erreicht wurden.\n");
        System.out.print("Adresse 1: ");
        String tmp1 = input.nextLine();
        System.out.print("Adresse 2: ");
        String tmp2 = input.nextLine();
        input.close();
        byte[] ip1 = ipv4ToBytes(tmp1);
        byte[] ip2 = ipv4ToBytes(tmp2);

        // Thread
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    String s = bytesToIpv4(ip1);
                    System.out.println("Die Adresse Thread 1 ist " + s);
                    synchronized (ip2) {
                        if (Arrays.equals(ip1, ip2) || !countUp(ip1)) {
                            System.out.println("Thread 1 exit");
                            break;
                        }
                    }
                }
            }
        };
        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    String s = bytesToIpv4(ip2);
                    System.out.println("Die Adresse Thread 2 ist " + s);
                    synchronized (ip1) {
                        if (Arrays.equals(ip2, ip1) || !countDown(ip2)) {
                            System.out.println("Thread 2 exit");
                            break;
                        }
                    }
                }
            }
        };
        new Thread(r1).start();
        new Thread(r2).start();
    }

    public static String bytesToIpv4(byte[] value) {
        return String.format("%d.%d.%d.%d", value[0] & 0xff, value[1] & 0xff, value[2] & 0xff, value[3] & 0xff);
    }

    public static boolean countUp(byte[] value) {
        int i = value.length - 1;
        while (true) {
            if ((value[i] & 255) == 255) {
                if (i == 0)
                    return false;
                value[i] = 0;
                i--;
            } else {
                value[i]++;
                return true;
            }
        }
    }

    public static boolean countDown(byte[] value) {
        int i = value.length - 1;
        while (true) {
            if ((value[i] & 255) == 0) {
                if (i == 0)
                    return false;
                value[i] = (byte) 255;
                i--;
            } else {
                value[i]--;
                return true;
            }
        }
    }

    public static byte[] ipv4ToBytes(String ip) {
        String[] parts = ip.split("\\.");
        byte[] result = new byte[4];
        for (int i = 0; i < result.length; i++)
            result[i] = (byte) Integer.parseInt(parts[i]);
        return result;
    }
}
 
Zuletzt bearbeitet von einem Moderator:
X

Xyz1

Gast
Ich Frage doch nur stellvertretend und der Fehler ist mir gar nicht aufgefallen, ich denke es wäre besser die mittlere IP herauszufinden und nicht zu synchronisieren...

Btw. Ja, Zugeständnis, ich habe den Code etwas ver(schlimm)bessert bevor ich ihn hier postete.
 

temi

Top Contributor
Hier ein andere Variante.

Ist das jetzt wirklich besser? Du synchronisierst jetzt auf ip1, bzw. ip2, aber es greift sowieso nur jeweils ein Thread auf diese Variable zu.

Meine schlichte Herangehenweise wäre, entweder wie schon @Tobias-nrw angeregt hat, jedem Thread seinen eigenen Bereich an IP-Adressen zur Bearbeitung zu geben.

Oder eine Liste von IP-Adressen zu erstellen und darauf zu synchronisieren. Dann können die Threads sich immer die nächste zu prüfende IP holen. Eine Alternative dazu wäre ein Set auf dem synchronisiert wird, in das jeder Thread die IP-Adressen schreibt, die er gerade prüft. Damit kann vor jeder neuen Prüfung geschaut werden, ob die Adresse bereits bearbeitet wurde.

Edit:

Der ganze Code ist (wie auch schon in einem anderen Thema bereits angedeutet) wenig objektorientiert. Ich würde eine Klasse "IPv4Range" vorsehen, die über eine threadsichere Methode "next()" die nächste Adresse der Range liefert. Diese kann dann von beliebig vielen Threads abgerufen und getestet werden.
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Die while Schleife macht hier keinen Sinn, da die Bedingung maximal 1 mal erfüllt sein kann. Wenn value[i] i == 256 --> value[i]-- --> value[i] -- --> Bedinung nicht mehr erfüllt.
Nein, die Schleife kann durchaus mehrfach durchlaufen werden, am einfachsten zu sehen mit {0,0,0,0}.

Fängt mit Index 3 an, 0 - 1 = -1 , -1 & 0xFF = 255, Bedingung ist also wahr.
Dann das gleiche mit Index 2, genau gleiche Rechnung, Bedingung ist weiterhin wahr.
Dann das gleiche mit Index 1, usw...


Da die Bedingung zum Abbruch des jeweiligen Threads die Gleichheit beider IP4 Adressen ist . Die Countfunktion aber immer nur die Letzte Stelle herauf oder herunter zählt --- > Nein es wird nicht immer abgebrochen.
Zählt wie gesagt nicht nur die letzte Stelle ;)


s1 ist der Scanner der zum Einlesen der ip4 Strings dient. Warum wird eine Variable synchronisiert, auf die gar nicht mehr zugegriffen wird?
Ob drauf zugegriffen wird ist egal, wichtig ist in dem Fall nur, dass alle Threads ein gemeinsames Objekt zum synchronisieren nutzen.
Für die Nutzung des Scanners gibts keinen Grund, es funktioniert allerdings, anders als deine Variante:

Ist das jetzt wirklich besser? Du synchronisierst jetzt auf ip1, bzw. ip2, aber es greift sowieso nur jeweils ein Thread auf diese Variable zu.
Eher deutlich schlechter - wenn jeder Thread eine eigenes Objekt zum synchronisieren hat, ist das sinnlos.
In diesem Fall verändert Thread1 ip1, während Thread2 lesend darauf zugreift.
 

temi

Top Contributor
Für die Nutzung des Scanners gibts keinen Grund, es funktioniert allerdings

Naja, korrekter wäre: Die Synchronisation auf den Scanner funktioniert zwar, aber sie bewirkt nicht das, was damit bezweckt wurde. Es wird ja nicht verhindert, dass zwei Threads die gleiche IP (bzw. eine bereits getestete IP) testen.
 

Blender3D

Top Contributor
Eher deutlich schlechter - wenn jeder Thread eine eigenes Objekt zum synchronisieren hat, ist das sinnlos.
In diesem Fall verändert Thread1 ip1, während Thread2 lesend darauf zugreift.
Oder Thread1 vergleicht ip1 und ip2 und verbietet währen dessen den Schreibzugriff auf ip2, um zu verhindern dass eine Veränderung während des Vergleichs stattfindet.
 

mrBrown

Super-Moderator
Mitarbeiter
Naja, korrekter wäre: Die Synchronisation auf den Scanner funktioniert zwar, aber sie bewirkt nicht das, was damit bezweckt wurde. Es wird ja nicht verhindert, dass zwei Threads die gleiche IP (bzw. eine bereits getestete IP) testen.
Sie verhindert, das ein Thread ein Objekt verändert, während ein andere es liest. Das sie verhindert, dass eine IP mehrmals getestet wird, wurde doch von niemandem erwartet?
 

mrBrown

Super-Moderator
Mitarbeiter
Oder Thread1 vergleicht ip1 und ip2 und verbietet währen dessen den Schreibzugriff auf ip2, um zu verhindern dass eine Veränderung während des Vergleichs stattfindet.
Nein, lies dir noch mal durch, was synchronized bewirkt ;)

Auch wenn Thread 1 über ip2 synchronisiert, kann Thread 2 munter ip2 verändern.

Hier, ein ganz reduziertes Beispiel dazu, zwei Threads, einer synchronisiert über der Variable, der andere verändert:
Java:
public static void main(String[] args) {
    int[] ints = new int[1];

    new Thread() {
        @Override
        public void run() {
            synchronized (ints) {
                while (true) {
                    System.out.println("Thread1: " + ints[0]);
                }
            }
        }
    }.start();

    while (true) {
        ints[0]++;
    }

}
 

Blender3D

Top Contributor
Fängt mit Index 3 an, 0 - 1 = -1 , -1 & 0xFF = 255, Bedingung ist also wahr.
Dann das gleiche mit Index 2, genau gleiche Rechnung, Bedingung ist weiterhin wahr.
Dann das gleiche mit Index 1, usw...
Das sehe ich nicht so!
Java:
int i = value.lenght;   // i ist hier 4
i--; // i = 3
value[i]++;// Zugriff auf value[3] // hier werden die letzten 8 Bit verändert
while( (value[i] & 0xFF) == 255 ); // nur solange die letzen 8 Bit gesetzt sind
 

mrBrown

Super-Moderator
Mitarbeiter
Ich habe das mal so dem Titel entnommen und da ich im Code nichts anderes erkenne, was das bewerkstelligen könnte, nahm ich einfach an, dass es damit geplant gewesen ist.
Hm, stimmt, in Verbindung mit dem Titel könnte man das so verstehen, wenn das so gemeint war hast du natürlich recht und das synchronized ist dafür Unsinn :) Nötig ist es allerdings trotzdem, um gleichzeitige zugriffe zu verhindern.
 

mrBrown

Super-Moderator
Mitarbeiter
Das sehe ich nicht so!
Java:
int i = value.lenght;   // i ist hier 4
i--; // i = 3
value[i]++;// Zugriff auf value[3] // hier werden die letzten 8 Bit verändert
while( (value[i] & 0xFF) == 255 ); // nur solange die letzen 8 Bit gesetzt sind
Du hast jetzt aber nicht übersehen, dass das eine do-while-Schleife ist?

Probier es einfach aus, wenn dir mein Vorrechnen nicht reicht...
 
Zuletzt bearbeitet:

Blender3D

Top Contributor
Nein, lies dir noch mal durch, was synchronized bewirkt ;)

Auch wenn Thread 1 über ip2 synchronisiert, kann Thread 2 munter ip2 verändern.
14.5.7 Synchronisieren mit »synchronized« Zur nächsten Überschrift Zur vorigen Überschrift
Schon seit Java 1.0 können kritische Abschnitte mit synchronized geschützt werden. Im einfachsten Fall markiert der Modifizierer synchronized die gesamte Methode. Ein betretender Thread setzt bei Objektmethoden den Monitor des this-Objekts und bei statischen Methoden den Lock des dazugehörigen Class-Objekts.

Betritt ein Thread A eine synchronisierte Methode eines Objekts O und versucht anschließend Thread B eine synchronisierte Methode des gleichen Objekts O aufzurufen, muss der nachfolgende Thread B so lange warten, bis A wieder aus dem synchronisierten Teil austritt. Das geschieht, wenn der erste Thread A die Methode verlässt, denn mit dem Verlassen einer Methode – oder auch einer Ausnahme – gibt die JVM automatisch den Lock frei. Die Dauer eines Locks hängt folglich mit der Dauer des Methodenaufrufs zusammen, was zur Konsequenz hat, dass längere kritische Abschnitte die Parallelität einschränken und zu längeren Wartezeiten führen. Eine Endlosschleife in der synchronisierten Methode gäbe den Lock niemals frei.
 

Blender3D

Top Contributor
Du hast jetzt aber nicht übersehen, dass das eine do-while-Schleife ist?
Java:
int i = value.lenght;   // i ist hier 4
i--; // i = 3
value[i]++;// Zugriff auf value[3] // hier werden die letzten 8 Bit verändert 
// wenn hier die letzten Bits davor gesetzt waren sind sie es jetzt nicht mehr
// einziger Fall die letzten 8 Bits waren 1111 1110 -> 1111 1111 dann wird die Schleife wieder holt
while( (value[i] & 0xFF) == 255 ); // nur solange die letzen 8 Bit gesetzt sind

Würde die Schleife hier öfters als 3 mal Durchlaufen werden --> dann ist i = -1 und es folgt eine IndexOutofBounds Exception
value[-1] geht nicht.
Das geschieht aber nicht, da ein Mehrfachdurchlauf nicht stattfindet. Habe ich laufen lassen.
 

mrBrown

Super-Moderator
Mitarbeiter
14.5.7 Synchronisieren mit »synchronized« Zur nächsten Überschrift Zur vorigen Überschrift
Schon seit Java 1.0 können kritische Abschnitte mit synchronized geschützt werden. Im einfachsten Fall markiert der Modifizierer synchronized die gesamte Methode. Ein betretender Thread setzt bei Objektmethoden den Monitor des this-Objekts und bei statischen Methoden den Lock des dazugehörigen Class-Objekts.

Betritt ein Thread A eine synchronisierte Methode eines Objekts O und versucht anschließend Thread B eine synchronisierte Methode des gleichen Objekts O aufzurufen, muss der nachfolgende Thread B so lange warten, bis A wieder aus dem synchronisierten Teil austritt. Das geschieht, wenn der erste Thread A die Methode verlässt, denn mit dem Verlassen einer Methode – oder auch einer Ausnahme – gibt die JVM automatisch den Lock frei. Die Dauer eines Locks hängt folglich mit der Dauer des Methodenaufrufs zusammen, was zur Konsequenz hat, dass längere kritische Abschnitte die Parallelität einschränken und zu längeren Wartezeiten führen. Eine Endlosschleife in der synchronisierten Methode gäbe den Lock niemals frei.
Richtig, genau so funktioniert synchronized (wobei es in diesem Thread allerdings um Blöcke und nicht Methoden geht).

In deinem Code gibt es Thread 1 und Thread 2.
Thread 1 hat einen Block, der ip2 zur Synchronisierung nutzt, und Thread 2 nutzt ip1.

Solange sich Thread 1 in dem Block befindet, kann kein andere Thread sich in einem Block befinde, der auch ip2 zur Synchronisierung nutzt. Thread 2 nutzt allerdings ip1, die beiden synchronized-Blöcke sind also unabhängig voneinander und können gleichzeitig ausgeführt werden.
Und insbesondere können sie nicht nur gleichzeitig ausgeführt werden, Thread 1 kann auch ip2 verändern, während Thread 2 ip2 list (und andersrum mit ip1).

Damit sie nicht gleichzeitig ein Objekte schreiben und lesen, müssen beide Blöcke das selbe Objekt zum synchronisieren nutzen.

(Feinheiten wie wait mal außer acht gelassen)
 

mrBrown

Super-Moderator
Mitarbeiter
Würde die Schleife hier öfters als 3 mal Durchlaufen werden --> dann ist i = -1 und es folgt eine IndexOutofBounds Exception
value[-1] geht nicht.
Das geschieht aber nicht, da ein Mehrfachdurchlauf nicht stattfindet. Habe ich laufen lassen.
Keine Ahnung was du hast laufen lassen, aber ich bekomme bei passenden Werten jedes mal wie erwartete eine IndexOutOfBoundsException:

Code:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 4


Java:
public static void main(String[] args) {
    byte[] bs =new byte[]{0,0,0,0};
    count2(bs);
}

public static void count2(byte[] value) {

    int i = value.length;

    do {

      i--;
      value[i]--;
    } while ((value[i] & 0xFF) == 255);
  }
 
Zuletzt bearbeitet:
X

Xyz1

Gast
Mmm, ich komme bezüglich der doppelten Ausgabe auf keinen Grünen Zweig:
Java:
  private static volatile Boolean runs = true;
// ...
    Runnable r1 = new Runnable() {
      @Override
      public void run() {
        byte[] a = ip1;
        while (runs) {
          String s = bytesToIpv4(a);
          System.out.println("Die Adresse Thread 1 ist " + s);
          synchronized (runs) {
            if (runs) {
              if (isNotEquals(a, ip2)) {
                count(a);
              } else {
                runs = false;
              }
            }
          }
        }
      }
    };
 

mrBrown

Super-Moderator
Mitarbeiter
a) Speicher alle bereits ausgegebenen IPs und check jeweils vor der Ausgabe
b) Statt sich von zwei Seiten dem Mittelwert anzunähern, für einen expliziten "IpCounter" ein, aus dem sich alle Threads die nächste IP holen. Threads müssen dann nicht synchronisiert sein, nur der Counter muss das intern regeln
c) Variante b mit Queue und explizitem Generator-Thread, dieser legt IPs in eine Queue, Worker-Threads holen die sich da raus und testen sie
d) Den gesamten Bereich direkt aufteilen, jeder Thread kümmert sich nur um seinen Bereich



BTW: der übliche Weg für synchronized ist ein explizites "lock"-Object, was einfach nur zum synchronisieren genutzt wird. Das macht den Code meist einfacher lesbar, als wenn man irgendein beliebiges Objekt dafür "missbraucht".
 

temi

Top Contributor
b) Statt sich von zwei Seiten dem Mittelwert anzunähern, für einen expliziten "IpCounter" ein, aus dem sich alle Threads die nächste IP holen. Threads müssen dann nicht synchronisiert sein, nur der Counter muss das intern regeln

Ich hab es ja weiter oben schon geschrieben; die Möglichkeit b) wäre mein persönlicher Favorit, weil die Verarbeitung bei Bedarf sehr simpel auf zwei, drei oder noch mehr Threads verteilt werden kann.
 

mrBrown

Super-Moderator
Mitarbeiter
Ich hab es ja weiter oben schon geschrieben; die Möglichkeit b) wäre mein persönlicher Favorit, weil die Verarbeitung bei Bedarf sehr simpel auf zwei, drei oder noch mehr Threads verteilt werden kann.
Ja, sind im wesentlichen deine vier Varianten, nur anders formuliert.

Für beliebig viele Threads dürften sich alle vier Varianten nutzen lassen, wobei Variante d) da am unschönsten sein dürfte.
 

temi

Top Contributor
Just for fun und ohne Anspruch auf die Ideallösung:

Intern wird für die IP ein long verwendet, dann kann man einfach addieren um die nächste Adresse zu erhalten. Wer mag kann auch gerne noch ein paar zusätzliche Threads verwenden.

Java:
public final class Ipv4 {

    private static final int MAX_SHIFT = 24;
    private static final int PART_SHIFT = 8;

    public Ipv4(String value) {
        String[] parts = value.split("\\.");

        if (parts.length != 4) {
            throw new IllegalArgumentException("IP string has no valid length");
        }

        long temp = 0;

        for (int part = 0; part < parts.length; part++) {
            temp += Long.parseLong(parts[part]) << (MAX_SHIFT - PART_SHIFT * part);
        }

        this.value = temp;
    }

    public Ipv4(long value) {
        this.value = value;
    }

    public long getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "Ipv4 {" +
                (value >> 24 & 0xFF) + "." +
                (value >> 16 & 0xFF) + "." +
                (value >>  8 & 0xFF) + "." +
                (value       & 0xFF) +
                "}";
    }

    private final long value;
}

Java:
public final class Ipv4Range {

    public Ipv4Range(final Ipv4 from, final Ipv4 to) {
        this.from = from.getValue();
        this.to = to.getValue();
        first();
    }

    public synchronized Ipv4 first() {
        return new Ipv4(current = from);
    }

    public synchronized Ipv4 next() {
        if (current <= to) {
            return new Ipv4(current++);
        }

        throw new NoSuchElementException("There is no next IP");
    }

    public synchronized boolean hasNext() {
        return current <= to;
    }

    private final long from, to;
    private long current;
}

Java:
public class Main {

    public static void main(String[] args) {

        Ipv4 from = new Ipv4("192.168.0.1");
        Ipv4 to = new Ipv4("192.168.0.25");

        Ipv4Range range = new Ipv4Range(from, to);

        // Thread 1
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                while (range.hasNext()) {
                    System.out.println("Die Adresse Thread 1 ist " + range.next());
                }
            }
        };

        // Thread 2
        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                while (range.hasNext()) {
                    System.out.println("Die Adresse Thread 2 ist " + range.next());
                }
            }
        };

        new Thread(r1).start();
        new Thread(r2).start();
    }
}

Code:
Die Adresse Thread 2 ist Ipv4 {192.168.0.2}
Die Adresse Thread 1 ist Ipv4 {192.168.0.1}
Die Adresse Thread 2 ist Ipv4 {192.168.0.3}
Die Adresse Thread 1 ist Ipv4 {192.168.0.4}
Die Adresse Thread 2 ist Ipv4 {192.168.0.5}
Die Adresse Thread 1 ist Ipv4 {192.168.0.6}
Die Adresse Thread 2 ist Ipv4 {192.168.0.7}
Die Adresse Thread 1 ist Ipv4 {192.168.0.8}
Die Adresse Thread 2 ist Ipv4 {192.168.0.9}
Die Adresse Thread 1 ist Ipv4 {192.168.0.10}
Die Adresse Thread 2 ist Ipv4 {192.168.0.11}
Die Adresse Thread 1 ist Ipv4 {192.168.0.12}
Die Adresse Thread 2 ist Ipv4 {192.168.0.13}
Die Adresse Thread 1 ist Ipv4 {192.168.0.14}
Die Adresse Thread 2 ist Ipv4 {192.168.0.15}
Die Adresse Thread 1 ist Ipv4 {192.168.0.16}
Die Adresse Thread 2 ist Ipv4 {192.168.0.17}
Die Adresse Thread 1 ist Ipv4 {192.168.0.18}
Die Adresse Thread 2 ist Ipv4 {192.168.0.19}
Die Adresse Thread 1 ist Ipv4 {192.168.0.20}
Die Adresse Thread 2 ist Ipv4 {192.168.0.21}
Die Adresse Thread 1 ist Ipv4 {192.168.0.22}
Die Adresse Thread 2 ist Ipv4 {192.168.0.23}
Die Adresse Thread 1 ist Ipv4 {192.168.0.24}
Die Adresse Thread 2 ist Ipv4 {192.168.0.25}
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Kleine Anmerkung zur Synchronisierung; zwischen hasNext und next können sich die beiden Threads in die Quere kommen. Wenn nur noch ein Element "vorhanden ist", bekommen beide bei hasNext true, next wirft aber dann bei einem eine Exception.

Man könnte da mit Optional statt der Exception arbeiten oder in Richtung Spliterator gehen.
 
X

Xyz1

Gast
Wenn ich es richtig sehe wird es nicht immer anhalten bzw eine NoSuchElementException geben weil hasNext( und next( zwar einzeln synchronisiert sind, allerdings nicht zusammen, wodurch hasNext true zurückgeben kann aber zwischenzeitlich ein anderer Thread auch next aufrufen kann.
 

temi

Top Contributor
Ist es nicht so, dass durch das "synchronized" auf der Methodenebene auf "this" gelockt wird?

Damit kann keine der synchronisierten Methoden betreten werden, solange ein Thread innerhalb einer der synchronisierten Methoden ist, oder?
 

mrBrown

Super-Moderator
Mitarbeiter
Was soll sich denn dann ändern?
Man spart sich hasNext und es kann keine Exception fliegen.

Ist es nicht so, dass durch das "synchronized" an der Methode auf "this" gelockt wird?

Damit kann auch keine synchronisierte Methode betreten werden, solange ein Thread innerhalb einer der synchronisierten Methoden ist, oder?
Ja, aber bei zwei Methoden schlägt das fehl:

Thread 1 ruft hasNext auf und bekommt true
Thread 2 wartete bis Thread 1 zurückkehrt aus hasNext und ruft danach hasNext auf und bekommt true
Thread 1 wartete bis Thread 2 mit hasNext fertig ist und führt danach next aus, bekommt den Wert
Thread 2 wartete bis Thread 1 mit next fertig ist, ruft danach next auf und bekommt die Exception
 

mrBrown

Super-Moderator
Mitarbeiter
- IPv4 gibt nach außen nicht den long preis, stattdessen bekommt sie 'ne Methode um die IP zu inkrementieren.
- IPRange bekommt statt hasNext und next eine getNext, die ein Optional zurück gibt
- außerdem zusätzlich tryAdvance und forEachRemaining wie zB Spliterator das hat

Alle drei Varianten sollten sich parallel nutzen lassen, falls jemand Fehler sieht gerne drauf hinweisen :)

Java:
public class IPv4 implements Comparable<IPv4> {

    private static final int MAX_SHIFT = 24;

    private static final int PART_SHIFT = 8;

    private final long value;

    public IPv4(String value) {
        String[] parts = value.split("\\.");

        if (parts.length != 4) {
            throw new IllegalArgumentException("IP string has no valid length");
        }

        long temp = 0;

        for (int part = 0; part < parts.length; part++) {
            temp += Long.parseLong(parts[part]) << (MAX_SHIFT - PART_SHIFT * part);
        }

        this.value = temp;
    }

    private IPv4(long value) {
        this.value = value;
    }

    public IPv4 increment() {
        return new IPv4(this.value+1);
    }

    @Override
    public String toString() {
        return "" +
               (value >> 24 & 0xFF) + "." +
               (value >> 16 & 0xFF) + "." +
               (value >> 8 & 0xFF) + "." +
               (value & 0xFF);
    }

    @Override
    public int compareTo(final IPv4 that) {
        return Long.compare(this.value, that.value);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }
        final IPv4 that = (IPv4) o;
        return this.value == that.value;
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

}

Java:
public class IPv4Range {

    private final IPv4 from;

    private final IPv4 to;

    private IPv4 current;

    public IPv4Range(final IPv4 from, final IPv4 to) {
        this.from = from;
        this.to = to;
        this.current = this.from;
    }

    void forEachRemaining(Consumer<? super IPv4> action) {
        while (this.tryAdvance(ip -> System.out.printf("%s: %s%n", Thread.currentThread().getName(), ip)));
    }

    /**
     * @see Spliterator#tryAdvance(Consumer)
     */
    boolean tryAdvance(Consumer<? super IPv4> action) {
        Optional<IPv4> ip = getNext();
        if (ip.isEmpty()) {
            return false;
        }
        action.accept(ip.get());
        return true;

    }

    public synchronized Optional<IPv4> getNext() {
        if (!hasNext()) {
            return Optional.empty();
        }
        return Optional.of(next());
    }

    private IPv4 next() {
        if (hasNext()) {
            IPv4 next = current;
            current = current.increment();
            return next;
        }
        throw new NoSuchElementException("There is no next IP");
    }

    private boolean hasNext() {
        return current.compareTo(to) <= 0;
    }

}

Java:
public class Main {

    public static void main(String[] args) {

        IPv4 from = new IPv4("192.168.0.1");
        IPv4 to = new IPv4("192.168.1.0");

        IPv4Range range = new IPv4Range(from, to);

        Runnable withOptional = new Runnable() {
            @Override
            public void run() {
                for (Optional<IPv4> ip = range.getNext(); ip.isPresent(); ip = range.getNext()) {
                    System.out.printf("%s: %s%n", Thread.currentThread().getName(), ip.get());
                }
            }
        };

        Runnable withTryAdvance = new Runnable() {
            @Override
            public void run() {
                while (range.tryAdvance(ip -> System.out.printf("%s: %s%n", Thread.currentThread().getName(), ip))) {

                }
            }
        };
        Runnable withForEachRemaining = new Runnable() {
            @Override
            public void run() {
                range.forEachRemaining(ip -> System.out.printf("%s: %s%n", Thread.currentThread().getName(), ip));
            }
        };

        new Thread(withOptional).start();
        new Thread(withTryAdvance).start();
        new Thread(withForEachRemaining).start();
    }

}
 

httpdigest

Top Contributor
Hier eine Lösung mit einer einzigen next() Methode und AtomicReference (man könnte auch AtomicInteger nehmen, aber ich wollte nicht den int der Ipv4 nach außen geben - ach ja, es muss kein long sein, ein int reicht; sind ja nur 4 Bytes) plus noch ein paar Hilfsmethoden:
Java:
import java.util.NoSuchElementException;
public class Ipv4 implements Comparable<Ipv4> {
  private final int value;
  public Ipv4(String value) {
    String[] parts = value.split("\\.");
    if (parts.length != 4) {
      throw new IllegalArgumentException("IP string has no valid length");
    }
    int temp = 0;
    for (String part : parts) {
      int parti = Integer.parseInt(part);
      if (parti < 0 || parti > 255)
        throw new IllegalArgumentException("IP part has invalid value: " + part);
      temp = (temp << 8) + parti;
    }
    this.value = temp;
  }
  public Ipv4(int value) {
    this.value = value;
  }
  public Ipv4Range to(Ipv4 end) {
    return new Ipv4Range(this, end);
  }
  public Ipv4 next() {
    if (value == -1)
      throw new NoSuchElementException();
    return new Ipv4(value + 1);
  }
  @Override
  public String toString() {
    return "Ipv4 {" + (value >> 24 & 0xFF)
          + "." + (value >> 16 & 0xFF)
          + "." + (value >> 8  & 0xFF)
          + "." + (value       & 0xFF) + "}";
  }
  @Override
  public int compareTo(Ipv4 o) {
    return Integer.compare(value, o.value);
  }
}
Java:
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
public class Ipv4Range {
  private final Ipv4 to;
  private final AtomicReference<Ipv4> current;
  public Ipv4Range(Ipv4 from, Ipv4 to) {
    this.to = to;
    this.current = new AtomicReference<Ipv4>(from);
  }
  /**
   * @return the next {@link Ipv4} in this range;
   *         or <code>empty</code> if all Ipv4 instances
   *         of this range have been returned
   */
  public Optional<Ipv4> next() {
    Ipv4 curr, next;
    do {
      if ((curr = current.get()).compareTo(to) >= 0)
        return Optional.empty();
    } while (!current.compareAndSet(curr, next = curr.next()));
    return Optional.of(next);
  }
}
Java:
public class Main {
  public static void main(String[] args) {
    Ipv4Range range = new Ipv4("192.168.0.1").to(new Ipv4("192.168.4.25"));
    Runnable r1 = () -> {
      Ipv4 next = null;
      while ((next = range.next()) != null) {
        System.out.println(Thread.currentThread() + " -> " + next);
      }
    };
    for (int i = 0; i < 8; i++)
      new Thread(r1).start();
  }
}
 
Zuletzt bearbeitet:
K

kneitzel

Gast
Also die Lösungen sind doch alle schon recht schön aufbereitet und dem kann ich nur wenig beisteuern.

Eine Lösung, die mir durch den Kopf geht und ich kurz anmerken möchte, gerade weil sie einfach und schnell ohne diese hohe Komplexität zu schreiben ist: Nutzung von Stream.
- Man will etwas für jede IP aus einerm IP-Bereich machen: Hier kann man die IP Adressen schön als Integer Werte sehen, so dass man ein einfachen Stream von Ints hat
- Diesen Stream kann man nun parallel abarbeiten dank .parallel()
- Die eigentliche Aktion landet dann in .foreach verarbeiten.

Eine solche Lösung bietet sich hier durchaus an, da der eigentliche Task relativ einfach ist und es zwischen den Tasks keine Abhängigkeiten / Wechselwirkungen gibt.

So wird aus der Thematik ein relativ simpler, verständlicher Code, der aus wenigen Methoden und eben der Stream Lösung besteht.

Bezüglich dieser Lösung würde ich einfach einmal folgenden Link anführen (Angelika Langer hat aber diesbezüglich deutlich mehr geschrieben, aber das ist ein interessanter Artikel von Ihr. Generell findet sich bei Ihr aber sehr viel Interessantes.
http://www.angelikalanger.com/Artic...ms/82.Java8.Performance-Model-of-Streams.html

Viele Grüße,

Konrad
 
X

Xyz1

Gast
zufrieden bin ich mit dem alle dem noch nicht, da Synchronisierung und Streams Zeit kosten und durch Parallelisierung eigentlich diese eingespart werden sollte. Jetzt ist die eigentliche Rechenoperation nur minimal (nur eine Ausgabe), aber es wär durchaus ja möglich, auch intensivere Operationen parallelisieren zu müssen...

Bearbeitung: Ich bin jetzt Kuchenessen....
 

mrBrown

Super-Moderator
Mitarbeiter
- Man will etwas für jede IP aus einerm IP-Bereich machen: Hier kann man die IP Adressen schön als Integer Werte sehen, so dass man ein einfachen Stream von Ints hat
Wobei man es ja eigentlich vermeiden will, IPs nur als int zu repräsentieren (zumindest ich), einen Stream von ints würde ich daher als Nachteil sehen
 

mrBrown

Super-Moderator
Mitarbeiter
zufrieden bin ich mit dem alle dem noch nicht, da Synchronisierung und Streams Zeit kosten und durch Parallelisierung eigentlich diese eingespart werden sollte. Jetzt ist die eigentliche Rechenoperation nur minimal (nur eine Ausgabe), aber es wär durchaus ja möglich, auch intensivere Operationen parallelisieren zu müssen...

Bearbeitung: Ich bin jetzt Kuchenessen....
Wenn du keinerlei synchronisierung willst, Teil das vorher in passende Bereiche für jeden Thread auf, dann kann jeder unabhängig von den anderen arbeiten.

(Hat allerdings auch Nachteile, falls ein Thread signifikant länger braucht, alle anderen sind dann fertig und müssen auf diesen einen warten)
 
K

kneitzel

Gast
Wobei man es ja eigentlich vermeiden will, IPs nur als int zu repräsentieren (zumindest ich), einen Stream von ints würde ich daher als Nachteil sehen
Es geht ja hier nicht darum, wie es ausgegeben wird. Ausgeben würde ich eine IP auch immer rein die typischen 4 Zählen, getrennt durch Punkte. Aber intern sind und bleiben es eben genau die 4 Bytes und mit diesen lässt sich nun einmal sehr gut rechnen.

Aber natürlich: ich würde Code so nicht wirklich stehen lassen. Daten, die etwas bedeuten, werden gekapselt und dann entsprechend benutzt.

Aber generell würde ich bei so Themen halt eine Standard Lösung bevorzugen. Abarbeitung eines Vorrats ist halt eine Thematik, bei der z.B. TheadPools und so durchaus brauchbar sind. Aber bezüglich diverser möglicher Pattern wurde ja schon viel geschrieben, so dass ich da nicht weiter drauf eingehen möchte. Aber die Parallelen Streams sind halt eine einfache, unkomplizierte schnelle Lösung für sowas.
 
X

Xyz1

Gast
So hätte ich das mit Streams gemacht:
Java:
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Optional;
import java.util.Scanner;
import java.util.stream.IntStream;

public class Unittest {
  private static Scanner s1;
  private static String p1, p2, p3;

  public static int ipToInt(String ip) throws UnknownHostException {
    byte[] a = InetAddress.getByName(ip).getAddress();
    return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0);
  }

  public static String ipToString(int ip) {
    return String.format("%d.%d.%d.%d", (ip >>> 24) & 0xFF, (ip >>> 16) & 0xFF, (ip >>> 8) & 0xFF, (ip >>> 0) & 0xFF);
  }

  public static synchronized Optional<String> getNext() {
    if (p3.equals(p2)) {
      return Optional.empty();
    }
    try {
      p3 = ipToString(ipToInt(p3) + 1);
    } catch (UnknownHostException e) {
      e.printStackTrace();
    }
    return Optional.of(p3);
  }

  public static void main(String[] args) throws UnknownHostException {
    s1 = new Scanner(System.in);
    System.out.println("Adresse 1: ");
    p1 = ipToString(ipToInt(s1.nextLine()) - 1);
    System.out.println("Adresse 2: ");
    p2 = s1.nextLine();
    p3 = p1;

    IntStream.rangeClosed(0, ipToInt(p2) - ipToInt(p1)).mapToObj(e -> getNext()).filter(e -> e.isPresent())
        .forEach(System.out::println);

    p3 = p1;
    IntStream.rangeClosed(0, ipToInt(p2) - ipToInt(p1)).parallel().mapToObj(e -> getNext()).filter(e -> e.isPresent())
        .forEach(System.out::println);
  }
}


Code:
Adresse 1: 
255.255.255.250
Adresse 2: 
255.255.255.255
Optional[255.255.255.250]
Optional[255.255.255.251]
Optional[255.255.255.252]
Optional[255.255.255.253]
Optional[255.255.255.254]
Optional[255.255.255.255]
Optional[255.255.255.250]
Optional[255.255.255.251]
Optional[255.255.255.252]
Optional[255.255.255.253]
Optional[255.255.255.254]
Optional[255.255.255.255]


Jetzt kann System.out::println eine sehr lange Operation sein wie zB Thread.sleep(100); dann würd sequential 600ms brauchen und parallel würd theoretisch nur 100ms brauchen... Richtig?
 
K

kneitzel

Gast
Wobei mein Streams Ansatz sogar deutlich weniger umfasst hätte, denn ich hätte da tatsächlich versucht es auf weniger zu konzentrieren. (Sprich: ohne viel drumherum für jede IP einen Consumer starten, Filter & Co würde ich da nicht betrachten. (Da kommen mir irgendwie zu viele Dinge in ein kurzes Stück Code ... ich teile gerne etwas mehr auf.)

Aber über die Sinnhaftigkeit bin ich mir selbst noch nicht ganz im Klaren. Hier im kleinen ist es ein einfacher Weg für die parallele Ausführung ohne viel Code schreiben zu müssen. Aber Java wird ja auch Thread Pools und so kennen und in einer Applikation will man ggf. ja mehr einstellen an Tasks während die anderen noch abgearbeitet werden. Daher fürchte ich, dass mir so eine Lösung evtl. Flexibilität nehmen könnte. Im Kleinen aber durchaus interessant.

Falls ich es heute Abend noch einmal an den Rechner schaffe, dann würde ich mal den Code basteln, wie ich es mir gedacht habe.. so am Tablet ist das gerade nicht wirklich möglich.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
javajoshi Problem mit zwei Threads und Arrays (Runnable) Java Basics - Anfänger-Themen 12
E join() bei zwei Threads Java Basics - Anfänger-Themen 2
M Threads, zwei methoden gleichzeitig laufen lassen Java Basics - Anfänger-Themen 4
L Mehr als zwei Threads synchronisieren Java Basics - Anfänger-Themen 7
M Zwei Threads greifen auf eine Methode einer Klasse zu. Komplikationen? Java Basics - Anfänger-Themen 18
Torschti Eingabe von Dezimalzahlen (bis zu zwei Kommastellen) Java Basics - Anfänger-Themen 11
A 1 Leerzeichen durch zwei Leerzeichen ersetzen Java Basics - Anfänger-Themen 4
K Warum wird mir hier nach dem ersten Durchlauf zwei mal "welchen Datentyp wollen sie übergeben?" ausgegeben ? Java Basics - Anfänger-Themen 1
sasnitzer java augensumme von zwei würfeln ist 1 Java Basics - Anfänger-Themen 8
krgewb Double mit zwei Nachkommastellen Java Basics - Anfänger-Themen 2
Distanz zwischen zwei Zeichenfolgen in einem String bestimmen Java Basics - Anfänger-Themen 5
D Größtes Palindrom Produkt aus zwei dreistelligen Zahlen Java Basics - Anfänger-Themen 60
berserkerdq2 Habe zwei exceptions, welche ist ein Kommunikationsfehler und welche ein Ausgabefehler? Java Basics - Anfänger-Themen 4
berserkerdq2 Zwei Klassen Erben von der Klasse A, die eine Klasse kann ich an Methoden übergeben, die als Parameter A haben, die andere nicht? Java Basics - Anfänger-Themen 3
B Erste Schritte Bisektion mit zwei Funktionen? Java Basics - Anfänger-Themen 1
G zwei Instanzen einer Klasse Java Basics - Anfänger-Themen 29
A Java-XSSFBook: zwei Sheets mergen Java Basics - Anfänger-Themen 5
C Zwei Arrays addieren und ausgeben Java Basics - Anfänger-Themen 3
J Speichern von zwei Variablen durch Auslesen aus einem Numberfield Java Basics - Anfänger-Themen 2
D Zwei verschiedene Intellij Projekte, wie benutze ich wechselseitig objekte Java Basics - Anfänger-Themen 8
berserkerdq2 Wie würde man einen regulären Ausdruck in Java schreiben, der prüft, dass zwei bestimtme Zahlen nicht nebeneinadner sind? Java Basics - Anfänger-Themen 3
K mit <<1 kann man mal 2 machen, mit >>2 geteilt durch zwei und was bewirkt <<<1 und >>>1? Java Basics - Anfänger-Themen 5
Dorfschmied Kartesisches Produkt von zwei Liste mit Hashmaps<String,String> erstellen Java Basics - Anfänger-Themen 4
F Abstand zwischen zwei Objekten berechnen wie? Java Basics - Anfänger-Themen 1
M Wie kann ich ein Array in zwei Hälften aufteilen? Java Basics - Anfänger-Themen 12
S Längster Pfad zwischen zwei Vertices in einem Graph Java Basics - Anfänger-Themen 3
S Aktuell beste Methode um zwei Bilder zu vergleichen..? Java Basics - Anfänger-Themen 1
A Zwei XML-Dateien Mergen Java Basics - Anfänger-Themen 14
U Erste Schritte nextGaussian zwischen zwei Werten Java Basics - Anfänger-Themen 19
S Multiplikation von zwei Labels Java Basics - Anfänger-Themen 7
U zwei 2D arrays auf gleich sein überprüfen Java Basics - Anfänger-Themen 14
Bademeister007 Elemente aus zwei verschiedenen Arrays miteinander vergleichen und gegeben falls entfernen Java Basics - Anfänger-Themen 14
Düsseldorf2002 Datentypen Zwei dimensionale LinkedList Java Basics - Anfänger-Themen 8
S Objekte von zwei klassen in zwei verschiedene Textdateien schreiben Java Basics - Anfänger-Themen 5
J Zwei Objekte vergleichen Java Basics - Anfänger-Themen 8
X Zwei Dimensionales Array prüfen Java Basics - Anfänger-Themen 1
G Methoden Informationen aus zwei Objekte bekommen? Java Basics - Anfänger-Themen 6
E Wie gebe ich alle Daten zwischen zwei Zeitpunkten aus? Java Basics - Anfänger-Themen 2
Q Besitzen zwei Strings identische Buchstaben, nur in anderer Reihenfolge? Java Basics - Anfänger-Themen 10
pkm Regexproblem - Wie kann ich zwei oder mehr beliebige Zeichen matchen? Java Basics - Anfänger-Themen 7
A Wieso bekomme ich hier zwei unterschiedliche Ausgaben? Java Basics - Anfänger-Themen 6
H Ein gegebenes Int Array zu Zwei Arrays zurück geben Java Basics - Anfänger-Themen 6
J zwei String Arrays miteinander vergleichen Java Basics - Anfänger-Themen 18
R Methode zwei Sortierkriterien der Klasse Comparator übergeben Java Basics - Anfänger-Themen 4
B Collections.sort mit zwei Bedingungen? Java Basics - Anfänger-Themen 4
X Textdatei: zwei-zeilenweise gleiche Zeilen rausschmeißen Java Basics - Anfänger-Themen 21
M Konkatenation von zwei Strings Java Basics - Anfänger-Themen 6
J Problem beim vergleich von zwei Integer Java Basics - Anfänger-Themen 3
D Input/Output Input von zwei Koordinaten validieren und anschließend Werte speichern Java Basics - Anfänger-Themen 7
L Zwei sortierte Subarrays mit gleicher Länge zusammenfügen Java Basics - Anfänger-Themen 2
F Zwei Dimensionles Array Java Basics - Anfänger-Themen 21
I Alle Elemente von zwei Listen vergleichen Java Basics - Anfänger-Themen 1
J Inhalte von zwei Arrays vertauschen?! Java Basics - Anfänger-Themen 6
O zwei Arrays nach Werten durchsuchen und zusammenfügen Java Basics - Anfänger-Themen 3
A Wie zwei zahlen in einer Variable speichern? Java Basics - Anfänger-Themen 7
N Zwei Daten (Datum) miteinander vergleichen, abspeichern, laden Java Basics - Anfänger-Themen 4
B Relativen Anteil von zwei Datümer auf Monatsebene umrechnen Java Basics - Anfänger-Themen 130
W Zwei Programme sollen auf eine Klasse zugreifen Java Basics - Anfänger-Themen 18
B Rückgabe von zwei Werten: String und double Java Basics - Anfänger-Themen 14
J Zwei Klassen die sich gegenseitig referenzieren - Bad practice? Java Basics - Anfänger-Themen 4
B Anzahl von Stunden / Tage von zwei Datumswerten ermitteln Java Basics - Anfänger-Themen 1
L Erste Schritte Elemente zwei Schlangen vergleichen Java Basics - Anfänger-Themen 14
N Zwei Strings mit "==" vergleichen warum TRUE Java Basics - Anfänger-Themen 2
D Input/Output InputDialog mit zwei Inputfeldern? Java Basics - Anfänger-Themen 4
D Funktion zwei Arraylisten zu verleichen ob gleich funktioniert nicht Java Basics - Anfänger-Themen 26
S Daten aus zwei Verschiedenen Tabellen in eine ArrayListe Java Basics - Anfänger-Themen 4
D Zwei Strings sind gleich bei if aber nicht true Java Basics - Anfänger-Themen 2
E Best Practice Jar-file mit zwei Klassen und externer Bibliothek über Konsole erzeugen Java Basics - Anfänger-Themen 13
J Logging erzeugt zwei dateien.... Java Basics - Anfänger-Themen 7
S zwei-dimensionales Array Java Basics - Anfänger-Themen 20
R Zwei Attribute gleichzeitig ausgeben Java Basics - Anfänger-Themen 12
T Classpath Zwei gleiche Dateinamen in verschiedenen Projekten möglich? Java Basics - Anfänger-Themen 13
H Bubblesort-Zwei Integer auf Dekade vergleichen. Java Basics - Anfänger-Themen 6
M Wie erzeuge ich die Differenz von zwei Daten in Stunden?? Java Basics - Anfänger-Themen 2
L Den Winkel zwischen zwei Vektoren berechnen! Java Basics - Anfänger-Themen 2
jaleda100 KeyCode – zwei Tasten gleichzeitig Java Basics - Anfänger-Themen 2
M Methoden Zwei Methoden in einem Program laufen lassen...aber wie? Java Basics - Anfänger-Themen 2
M Methoden zwei methoden gleichzeitig laufen lassen Java Basics - Anfänger-Themen 4
M For-Schleife durch zwei versch. Variablen begrenzen Java Basics - Anfänger-Themen 27
B Erste Schritte Problem bei der Verknüpfung von zwei klassen Java Basics - Anfänger-Themen 8
J Methoden Zwei Methoden die fast das gleiche tun organisieren Java Basics - Anfänger-Themen 3
Bluedaishi der Monat zwischen zwei Datumsangaben Java Basics - Anfänger-Themen 15
J Best Practice Datum Differenz aus zwei Strings ermitteln Java Basics - Anfänger-Themen 8
J Ein Objekt and eine Methode übergeben zwei Schreibweisen? Java Basics - Anfänger-Themen 6
R Threads Pause zwischen zwei Schleifen Java Basics - Anfänger-Themen 1
Aprendiendo Zwei Fragen und ein geerbtes "protected"-Attribut Java Basics - Anfänger-Themen 2
S Parameterübergabe zwischen zwei Programme Java Basics - Anfänger-Themen 4
L Rekursiv zwei Strings vergleichen Java Basics - Anfänger-Themen 3
L Classpath Zwei Bibliotheken enthalten gleiche .class Datei Java Basics - Anfänger-Themen 6
S OOP Zwei JSlider in einer Klasse Java Basics - Anfänger-Themen 2
P Aus einem Array zwei Arrays machen Java Basics - Anfänger-Themen 3
ArkHeat Erste Schritte Zwei 2-dimensionale Matritzen addieren Java Basics - Anfänger-Themen 0
S Erste Schritte Zwischen zwei Punkten ein Minimumpkt./Maxima finden Java Basics - Anfänger-Themen 1
T OOP Zwei Klassen Testen (Arrary Iterieren) Java Basics - Anfänger-Themen 6
E Eine Instanzvariable und zwei Objekte Java Basics - Anfänger-Themen 14
S Durchschnitt berechnen aus zwei Textfeldern Java Basics - Anfänger-Themen 21
K Zwei Fragen zu Graphics/Graphics2D Java Basics - Anfänger-Themen 5
P Verbindung von Zwei Kreisen löschen ! Java Basics - Anfänger-Themen 6
J Zwei String-Variabeln vergleichen Java Basics - Anfänger-Themen 5
F Vererbung in zwei Richtungen? Java Basics - Anfänger-Themen 14

Ähnliche Java Themen

Neue Themen


Oben