Programmeren in Java/Multithreading

Uit Wikibooks
Naar navigatie springen Naar zoeken springen


Programmeren in Java In ontwikkeling. Revisiedatum: onbekend

  1. Inleiding Redelijk ontwikkeld. Revisiedatum: 22 augustus 2008
  2. Basis Goed ontwikkeld. Revisiedatum: 24 november 2007
  3. In- & uitvoer In ontwikkeling. Revisiedatum: 24 november 2007
  4. Stringbewerkingen In ontwikkeling. Revisiedatum: 24 november 2007
  5. Arrays Nog vrijwel niets. Revisiedatum: 24 november 2007
  6. Collections Nog vrijwel niets. Revisiedatum: 24 november 2007
  7. Exceptions Redelijk ontwikkeld. Revisiedatum: 24 november 2007
  8. Generics Nog vrijwel niets. Revisiedatum: 24 november 2007
  9. Ingebouwde functies Nog vrijwel niets. Revisiedatum: 20 januari 2007
  10. Multithreading Nog vrijwel niets. Revisiedatum: 20 januari 2007
  11. GUI In ontwikkeling. Revisiedatum: 24 november 2007
  12. JSP: JavaServer Pages Redelijk ontwikkeld. Revisiedatum: 24 november 2007

Klassen

  1. Klassen Goed ontwikkeld. Revisiedatum: 24 november 2007
  2. Overerving In ontwikkeling. Revisiedatum: 20 januari 2007
  3. Geavanceerde klassen In ontwikkeling. Revisiedatum: 24 november 2007

Design Patterns

  1. Strategy Pattern Nog vrijwel niets. Revisiedatum: 26 december 2010

Appendices

  1. Appendix A: Installatie In ontwikkeling. Revisiedatum: 24 november 2007
  2. Appendix B: Javadoc In ontwikkeling. Revisiedatum: 24 november 2007


Multithreading is het uitvoeren van meerdere taken tegelijkertijd, buiten java ook gekend onder de benaming multitasking. Bij computers die slechts één processor hebben, wordt het werk van de verschillende threads in kleine pakketjes afwisselend uitgevoerd. Als er meerdere processoren aanwezig zijn, kan er echt parallel gewerkt worden.

draad extends Thread[bewerken]

Voorbeelden zijn bvb. het wegschrijven door de tekstverwerker van een bestand op de achtergrond, terwijl je al verdertypt.

Uitdrukkingen
  • public void run() bevat de uit te voeren code.
  • start() creëert de extra thread, en de JVM voert de run() uit.
  • sleep(int mills) om de thread een aantal milliseconden te laten pauzeren.
  • name
  • priority verdeelt de processortijd tussen de verschillende threads. De waarde ligt tussen MIN_PRIORITY (1) en MAX_PRIORITY (10).
Voorbeeld

Java-code: draad.java

import java.io.*;
public class draad extends Thread{
  private String naam;
  private int aantal;
  private int kolom;
  private String s;
  public draad(String threadName, String naam, int aantal, int kolom) { // constructor
    super(threadName);
    this.naam = naam;
    this.aantal = aantal;
    s = " ";
    for (int j = 0; j < kolom; j++)
      s = "\t" + s;
    s = s + "x";
  }
  public void run() {
    for (int i = 0; i < aantal; i++) {
    System.out.println(naam + i + s);
    }
  }           
}

Java-code: multi.java

public class multi {
  public static void main(String[] args) {
    draad reeksA = new draad("taakA","A",10,1);
    draad reeksB = new draad("taakB","B",10,2);
    draad reeksC = new draad("taakC","C",10,3);
    reeksA.start();
    reeksB.start();
    reeksC.start();
  }
}

Als we dit laten lopen, zien we dat het werk mooi verdeeld wordt over de verschillende threads:

A0	 x
B0		 x
C0			 x
A1	 x
B1		 x
C1			 x
...
A8	 x
B8		 x
C8			 x
A9	 x
B9		 x
C9			 x

draad2 implements Runnable[bewerken]

Een iets omslachtiger methode behaalt hetzelfde resultaat als hierboven:

Uitdrukkingen
  • public void run() bevat de uit te voeren code.
  • start()
  • .currentThread().getName()
Voorbeeld

Java-code: draad2.java

import java.io.*;
public class draad2 implements Runnable{
  private String naam;
  private int aantal;
  private int kolom;
  private String s;
  public draad2(String naam, int aantal, int kolom) {
    this.naam = naam;
    this.aantal = aantal;
    s = " ";
    for (int j = 0; j < kolom; j++)
      s = "\t" + s;
    s = s + "x";
  }
  public void run() {
    for (int i = 0; i < aantal; i++) {
      System.out.println(naam + i + s);
    }          
  }
}

Java-code: multi2.java

public class multi2 {
  public static void main(String[] args) {
    draad2 reeksA = new draad2("A",10,1); 
    draad2 reeksB = new draad2("B",10,2);
    draad2 reeksC = new draad2("C",10,3);
    Thread t1 = new Thread(reeksA, "taakA");
    Thread t2 = new Thread(reeksB, "taakB");
    Thread t3 = new Thread(reeksC, "taakC");
    t1.start();
    t2.start();
    t3.start();
  }
}

Synchronisatie[bewerken]

Tegelijk lopende verrichtingen kunnen elkaar storen. Daarom kan je objecten blokkeren, zodat ze slechts door één thread tegelijkertijd kunnen gebruikt worden. Als echter de ene thread wacht op het vrijkomen van een object dat door een andere thread geblokkeerd wordt omdat het eerst het geblokkeerde object van de eerste thread nodig heeft, ontstaat een zgn. deadlock. Dit treedt ook soms op bij databanken, en dan zal een rollback uitgevoerd worden na een bepaalde deadtime.

Uitdrukkingen

In Java kan je dergelijke problemen best voorkomen:

  • wait() zal gedurende een bepaalde periode het object in de wacht zetten
  • notifyAll() haalt alle threads uit de wacht, zodat ze eventueel het object dat net vrijgegeven werd kunnen gebruiken
  • synchronised zorgt dat hiermee gemarkeerde methods niet tegelijkertijd worden uitgevoerd
Voorbeeld

Onderstaande Buffer wordt gevuld door de Producent en geleegd door de Consument, die beiden threads zijn die door het hoofdprogramma Synchro aangestuurd worden:

Java-code: Buffer.java

public class Buffer {
  private String inhoud;
  private boolean vullen = true; //Schakelaar: Starten met opvullen
  public synchronized String haalOp() {
    try {
      while (vullen)             //Wachten op opvulling voor er opgehaald wordt
        wait();
    } catch (Exception e) {}
    vullen = true;
    notifyAll();
    return inhoud;
  }
  public synchronized void vulOp(String inhoud) {
    try {
      while (!vullen)            //Wachten op ophaling voor er opnieuw opgevuld wordt
        wait();
    } catch (Exception e) {}
    this.inhoud = inhoud;
    vullen = false;
    notifyAll();
  }
}

Java-code: Producent.java

public class Producent implements Runnable {
  private String[] tekst;
  private Buffer buf;
  public Producent (String[] tekst, Buffer buf) {
    this.tekst = tekst;
    this.buf = buf;
  }
  public void run() {
    String lijn;
    int r = 0;
    while (r < tekst.length)
      buf.vulOp(lijn = tekst[r++]);
    buf.vulOp(null);
  }
}

Java-code: Consument.java

public class Consument implements Runnable { 
 private Buffer buf;
  private int aantalWoorden;
  public Consument (Buffer buf) {
    this.buf = buf;
    aantalWoorden = 0;
  }
  public void run() {
    String lijn;
    while ((lijn = buf.haalOp()) != null) {
      System.out.println(lijn);
      for (int i = 0; i < lijn.length(); i++) { // woorden tellen
        if (lijn.charAt(i) == ' ') 
          aantalWoorden++;
      }
      System.out.println("\t\tTussentotaal = " + ++aantalWoorden);;
    }
    System.out.println("Totaal aantal woorden = " + aantalWoorden);
  }
}

Java-code: Synchro.java

public class Synchro {
  public static void main(String[] args) {
    String[] tekst = {"Ode aan de vreugde", "Door Filip Muyzenhardt", "Paramaribo"};
    Buffer buf = new Buffer();
    Producent pro = new Producent(tekst, buf);
    Consument con = new Consument(buf);
    Thread t1 = new Thread(pro);
    Thread t2 = new Thread(con);
    t1.start();
    t2.start();
  }
}

Client- en Serverprocessen[bewerken]

Computers op een netwerk, als het internet, werken ook met processen die op elkaar wachten:

Java-code: TCPClient.java

import java.io.*; 
import java.net.*; 

class TCPClient { 
  public static void main(String argv[]) throws Exception { 
    String sentence; 
    String modifiedSentence; 
    
    BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));  //Create input stream
    Socket clientSocket = new Socket("localhost", 6789); //Create client socket, connect to server
    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); // Create output stream attached to socket
    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); // Create input stream attached to socket
    sentence = inFromUser.readLine(); 
    outToServer.writeBytes(sentence + '\n'); // Send line to server
    modifiedSentence = inFromServer.readLine(); // Read line from server
    System.out.println("FROM SERVER: " + modifiedSentence); 
    clientSocket.close(); 
    
  }
}

Onderstaand proces zal na opstarten de requesten van bovenstaand proces beantwoorden.

Java-code: TCPServer.java

import java.io.*; 
import java.net.*; 

class TCPServer { 
  public static void main(String argv[]) throws Exception { 
    String clientSentence; 
    String capitalizedSentence; 
    
    ServerSocket welcomeSocket = new ServerSocket(6789); // Create welcoming socket at port 6789
    
    while(true) { //loop back and wait for another client connection
      Socket connectionSocket = welcomeSocket.accept(); //Wait, on welcoming socket for contact by client
      BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); //Create input stream, attached to socket
      DataOutputStream  outToClient = new DataOutputStream(connectionSocket.getOutputStream()); //Create output stream, attached to socket
      clientSentence = inFromClient.readLine(); //Read in line from socket
      capitalizedSentence = clientSentence.toUpperCase() + "\n !!!"; 
      outToClient.writeBytes(capitalizedSentence); //Write out line to socket
    } 
  } 
}

Termen die met multi threading te maken hebben[bewerken]

Livelock: Een thread wacht op een andere thread met bv Thread.join() totdat hij aan het eind is.
Deadlock: 2 of meer threads die zo bezig zijn dat, ze niet meer iets kunnen doen, bv: thread A wacht totdat threat B eindigt en thread B wacht totdat thread A eindigt


Informatie afkomstig van http://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.