Mit der gleichen BlockingQueue in zwei Klassen arbeiten

n01sp

Mitglied
Hey Leute,
ich bin momentan dabei ein kleines Programm zu schreiben und hänge bei der richtigen Übergabe von einer BlockingQueue. Außerdem kann ich meine Threads nicht durch die Methode start() starten.

Java:
package de.sportreporter;

import java.awt.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import sun.misc.Queue;

/**
* Represents a server consuming comments of
* sport reporters, updating the output.
* 
*
*/
public class LiveTicker implements Runnable {
   
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(1000);
                BlockingQueue<String> puffer = getEventList();
                System.out.println(puffer);
                puffer.poll();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
       
        }
    }
   
    /**
     * @return returns the list containing the comments
     */
    public synchronized BlockingQueue<String> getEventList() {
        BlockingQueue<String> eventList = new LinkedBlockingQueue<String>();
        return eventList;
    }

    public static void main(String[] args){
        LiveTicker liveTicker = new  LiveTicker();
        SportReporter reporter1 = new SportReporter("München vs. Dortmund", liveTicker.getEventList());
        SportReporter reporter2 = new SportReporter("Berlin vs. Hamburg", liveTicker.getEventList());
        SportReporter reporter3 = new  SportReporter("Stuttgart vs. Köln", liveTicker.getEventList());
        liveTicker.start();
        reporter1.start();
       
   
    }
   
}

Java:
package de.sportreporter;

import java.util.Random;
import java.util.concurrent.BlockingQueue;



/**
* Represents a reporter posting comments of the current match to his
* live ticker.
* 
*
*/
public class SportReporter implements Runnable {
    private final String match;
      BlockingQueue<String> eventList;
     Random random;
   


    /**
     * Sport reporter used for comment a match.
     * @param match name of the match (e.g. names of the playing teams)
     * @param eventList list for posting the comments
     */
    public SportReporter(String match, BlockingQueue<String> eventList) {
        this.match = match;
        this.eventList = eventList;
    }
   
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(random.nextInt(6000));
                int pick4 = new Random().nextInt(SoccerEvent.values().length);
                eventList.add(SoccerEvent.values()[pick4].toString());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

       
        }
    }

}
Java:
package de.sportreporter;

/**
* Enum class containing all possible football match events.
* 
*
*/
public enum SoccerEvent {
   
    FOUL("Faulspiel"), GOAL("Tor"), OFFSIDE("Abseits"), CORNER("Eckball"), TACKLING("Zweikampf");
   
    private final String catchword;
    SoccerEvent(String catchword){
        this.catchword = catchword;
    }
   
    /**
     * @return returns the German word for the event
     */
    public String getCatchword() {
        return catchword;
    }
}
 
getEventList() erstellt bei jedem Aufruf eine neue Queue, jedes Objekt, welche eine erhält, erhält also eine andere, und beim ausgeben wird auch jedes mal der Inhalt einer grad neu erstellten ausgegeben.
Du solltest aus deiner Queue eine Instanzvariable in LiveTicker machen 😉
 
Hey , ich glaube ich habe da ein kleine Verständnisproblem. Ist es nicht so dass wenn vor die Deklarierung nichts schreibe , dass es dann automatisch eine INstanzvariable ist und nur wenn static da steht eine Klassenvaribale?
In meinem fall erstelle ich ja 3 mal eine Instanz/Thread vom Typen SportReporte und deshalb erstellt er doch auch nur eine Liste oder sehe ich das faslch?
 
Es steht in einer Methode, also ist es nur eine Methodenvariable. Instanz/Klassenvariable ist es nur, wenn es außerhalb einer Methode steht.

Es wird mit jedem Methodenaufruf der Code in der Methode neu ausgeführt, also auch jedes mal mit new ein neues Objekt erstellt, also bekommen alle eine eigene Queue
 
Ja du erstellst 3 Objekte der Klasse SportReportert und übergibst diesen im Konstruktor ein Listen Objekt. Das Problem liegt aber wo bzw. wie dieses Listen Objekt erstellt wird.
Es wird nämlich bei jedem Aufruf von getEventList() ein neues Listen Objekt erstellt.

Sprich jedes der SportReporter Objekte hat eine andere Liste, und dein LiveTicker Objekt erzeugt auch immer wieder eine neue Liste.

EDIT:
lokale Variablen: werden innerhalb einer Methode oder eines Blockes deklariert
Instanzvariablen: werden außerhalb von Methoden deklariert
Klassenvariablen: werden außerhalb von Methoden und static deklariert
 
Java:
package de.sportreporter;

import java.awt.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import sun.misc.Queue;

/**
* Represents a server consuming comments of
* sport reporters, updating the output.
* 
*
*/
public class LiveTicker extends Thread {
    BlockingQueue<String> eventList = new LinkedBlockingQueue<String>();
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(1000);
                BlockingQueue<String> puffer = getEventList();
                System.out.println(puffer);
                puffer.poll();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
      
        }
    }
  
    /**
     * @return returns the list containing the comments
     */
    public synchronized BlockingQueue<String> getEventList() {
      
        return eventList;
    }

    public static void main(String[] args){
        LiveTicker liveTicker = new  LiveTicker();
        SportReporter reporter1 = new SportReporter("München vs. Dortmund", liveTicker.getEventList());
        SportReporter reporter2 = new SportReporter("Berlin vs. Hamburg", liveTicker.getEventList());
        SportReporter reporter3 = new  SportReporter("Stuttgart vs. Köln", liveTicker.getEventList());
        liveTicker.start();
        reporter1.start();

So wäre die Queue ja jetzt eine Instanzvariable, das Problem ist nur wie benutze ich denn die gleiche in der Klasse SportReporter? Ich dachte eigentlich wenn ich einen Sportreporter erzeuge, dass die klasse dann automatisch damit arbeitet scheint abe rnicht ganz zu funktionieren.
 
...das Problem ist nur wie benutze ich denn die gleiche in der Klasse SportReporter?
Das hast du doch schon erledigt: getEventList liefert dir deine Queue zurück, und jedem deiner SportReporter Objekte übergibst du ja dieses Liste
Ich dachte eigentlich wenn ich einen Sportreporter erzeuge, dass die klasse dann automatisch damit arbeitet scheint abe rnicht ganz zu funktionieren.
Das Problem ist die Liste wird nirgends initialisiert. Sprich deine SportReporter verweisen auf nichts (null)
Entweder du erstellst einen Konstruktor von LiveTicker und initialisierst dort die Liste oder du erstellst diese beim 1.Aufruf von getEventListe. Ich würde zum Konstruktor raten.

EDIT: Mein Fehler habe die Initialisierung nicht gesehen 😉
 
Zuletzt bearbeitet:
Mach mal ein Systemout in der Run Methode vom Sportreporter und deinem Liveticker von der Queue Variable, dann siehst du das die Variable auf die Gleiche Speichernaddresse Zeigt ...

Alle haben jetzt die Queue vom Liveticker, bzw du hast einmal new Queue im Code stehen...
 
Java:
package de.sportreporter;

import java.util.Random;
import java.util.concurrent.BlockingQueue;



/**
* Represents a reporter posting comments of the current match to his
* live ticker.
* 
*
*/
public class SportReporter extends Thread {
    public String match;
     public BlockingQueue<String> eventList;
     Random random;
   


    /**
     * Sport reporter used for comment a match.
     * @param match name of the match (e.g. names of the playing teams)
     * @param eventList list for posting the comments
     */
    public SportReporter(String match, BlockingQueue<String> eventList) {
        this.match = match;
        this.eventList = eventList;
    }
   
    @Override
    public void run() {
        while (true){
            int pick = new Random().nextInt(6000);
            try {
                Thread.sleep(pick);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
                int pick4 = new Random().nextInt(SoccerEvent.values().length);
                eventList.add(SoccerEvent.values()[pick4].toString());
           

       
        }
    }

}
Java:
package de.sportreporter;

import java.awt.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import sun.misc.Queue;

/**
* Represents a server consuming comments of
* sport reporters, updating the output.
* 
*
*/
public class LiveTicker extends Thread {
    BlockingQueue<String> eventList = new LinkedBlockingQueue<String>();
   
    public LiveTicker(){
        eventList = new LinkedBlockingQueue<String>();
    }
    @Override
    public void run() {
        while(true){
            if (!eventList.isEmpty()){
            try {
                Thread.sleep(1000);
                System.out.println(eventList.poll());
               
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
       
        }
        }
    }
   
    /**
     * @return returns the list containing the comments
     */
    public synchronized BlockingQueue<String> getEventList() {
       
        return eventList;
    }

    public static void main(String[] args){
        LiveTicker liveTicker = new  LiveTicker();
        SportReporter reporter1 = new SportReporter("München vs. Dortmund", liveTicker.getEventList());
        SportReporter reporter2 = new SportReporter("Berlin vs. Hamburg", liveTicker.getEventList());
        SportReporter reporter3 = new  SportReporter("Stuttgart vs. Köln", liveTicker.getEventList());
        liveTicker.start();
        reporter1.start();
        reporter2.start();
       
   
    }
   
}

So läuft jetzt!
Danke für eure Hilfe! Ihr seid echt Spitze!
Muss nur noch das jeweilige Match übergeben.
 
Die if Bedingung im Liveticker für zu einer undeutlich Schleife die 100 % deines cpu nutzt.

Du benötigst den if und Sleep nicht, da Poll bzw take blockiert falls die Queue leer ist. Damit läuft der Thread nicht kontinuierlich....

Warum benutzt du keinen ThreadPool bzw ExecutorService für das Ausführen von deinen Sportreportern? Vorsichtig gesagt wäre das Software technisch die sauberere Lösung?
 
Die if Bedingung im Liveticker für zu einer undeutlich Schleife die 100 % deines cpu nutzt.
Dem kann ich nur zustimmen. Anstatt eines while(true) solltest du eine echte/richtige Abbruchbedingung verwenden!

Du benötigst den if und Sleep nicht, da Poll bzw take blockiert falls die Queue leer ist. Damit läuft der Thread nicht kontinuierlich....

Warum benutzt du keinen ThreadPool bzw ExecutorService für das Ausführen von deinen Sportreportern? Vorsichtig gesagt wäre das Software technisch die sauberere Lösung?
Stimmt, das sleep(...) ist unnötig, aber auch ohne ThreadPool oder ExecutorService kann man das Programm "sauber" ausführen lassen.
 
Deswegen habe ich auch Vorsichtig im Satz und spreche von der Software technischen Seite. Natürlich kann man das Programm sauber ausführen, wobei es nicht beendet 😉 .

@Joose
Aber ein ExecutorService ist ja ne Queue mit Aufgabe oder nicht, wobei du die Queue und die zuabarbeiten Threads nicht implementieren musst ?
 
Das sleep ist in der methode drin weil eine Sekunde zwischen Kommentar in der Liste erstellen und ausgeben auf der Konsole sein soll.
 

Zurück
Oben