synchronen Schreibzugriff in den Griff bekommen

diabolik

Aktives Mitglied
Hallo zusammen,

ich habe folgendes Problem, mit einem essenziellen Teil eines sehr komplexen Programms:

Ich habe eine Klasse loggingController(), die, wie es ihr Name schon verrät, ausschliesslich dem Verwalten von LoggingInformationen dient. Vereinfacht dargestellt sieht diese wie folgt aus:

Java:
package JohnDo.Controller;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;


// ---------------------------------
//   Class: LoggingController
// ---------------------------------

public class LoggingController {

    // The singleton implementation
    //
    private static LoggingController sharedInstance = null;

    public static LoggingController getSharedInstance() {
        if (sharedInstance == null) {
            sharedInstance = new LoggingController();
        }
        return sharedInstance;
    }
    
    // Internal variables
    //    
   private String systemLog[][];    

	
    private LoggingController () {
        systemLog = new String[3][100]; // LoggingID, JobName, LoggingContent     
    }
   
	
    public void addSystemLogEntry(String loggingID, String entry) {
        // Neuen Logging-Eintrag anzeigen und speichern
        //
        
		for(int i=0; i<100; i++){
            if(systemLog[0][i].equals(loggingID)){
                length = systemLog[2][i].length();

                if(length + entry.length() >= 1000){ // spaeter nicht mehr als 1000 Zeichen in der GUI  anzeigen
                    systemLog[2][i] = entry + "§"; 
                }else{
                    systemLog[2][i] += entry + "§";
                }
                  
				// Hier wird das Logging (der Inhalt von "entry") in eine Datei geschrieben. 
				// Habe ich weggelassen, weil es an der Stelle nichts zur Sache tut.
		   }
        }
    }
	
	// Die Klasse umfasst noch weitere Logging-Bereichen, die alle nach dem gleichen Schema befuellt werden.
	// Auch gibt es Funktionen zum Auslesen der Loggings. Aber auch die tun hier nichts zur Sache, daher
	// lasse ich sie weg.
}


Mein Programm arbeitet mit vielen eigenständig agierenden Threads. Man muß sich das wie ein SchneeballSystem vorstellen.

Der AppController startet beim Laden der Anwendung den "JobStarterAndControllerThread()".
Der Anwender kann nun beliebig viele ProcessThreads() starten, die im JobStarterAndControllerThread() in ein ThreadArray gepackt werden und über Ihre Thread-ID angesprochen werden.

Diese ProcessThreads() wiederum sind der Starter für vollautomatisch und zeitgesteuert agierende Router-Abfragen, die, je nach Wunsch, über Minuten, Stunden und Tage durchlaufen und Ihre Arbeit in vorgegebenen Intervallen verrichten. Diese Abfragen bestehen aus einem ganzen Netzwerk separater Threads, von denen jeder seine Aufgabe hat.

Jeder Thread hat über die "import"-Funktion Zugriff auf die "SharedInstance()" des loggingControllers. Hier wieder eine vereinfachte Darstellung. Dieser Thread kann n mal parallel laufen.



Java:
package JohnDo.Threads.Processors;

// -------------------------------------------
//   Class: Physical Router System Defined Thread
// --------------------------------

import JohnDo.Controller.LoggingController;


public class PhysicalRouterSystemDefinedThread extends Thread{

    // Imported Classes
    //    
	private LoggingController loggingController = LoggingController.getSharedInstance();
	    
    // Internal Variables
	//
	private String loggingID = "";

	
    // Methods
    //
    public void start(String loggingID){
        this.loggingID = loggingID;    
	}
	
	
    public void run(){
    
        try{
			
            while(true){
                
	            // Prozesse, Prozesse, Prozesse
		       // Ploetzlich ist ein LoggingEintrag noetig

		       loggingController.setSystemLogEntry(this.loggingID, entry);
			
                 
                  Thread.sleep(100);
              }
           }catch(InterruptedException e){
                loggingController.setSystemLogEntry(this.loggingID, "Abbruch!");
		         this.interrupt();
           }
    }
}


Das heißt, ich habe mitunter mehrere 100 Threads, die irgendwann, ohne sich (bisher) abzusprechen, einen Eintrag in den loggingController() schreiben können. Mitunter passiert das synchron, sprich: auf die Millisekunde genau.

Und dabei gehen mir immer wieder LoggingInformationen verloren.


Daher meine Frage:

Wie kann ich es schaffen, dass absolut jede Logging-Information erfasst wird, auch wenn diese synchron mit anderen eintrifft?



Ich habe es schon mit dem Zusatz "synchronized" versucht, aber das hat nichts geaendert. Wobei ich eher vermute, dass ich "synchronized" hier völlig falsch einsetze...
 
Zuletzt bearbeitet:

KrokoDiehl

Top Contributor
Zunächst einmal die ketzerische Frage: Warum verwendest du keine bereits vorhandenen Bibliotheken (z.B. log4j) zum Logging. Ich bin mir sicher, dass man sich dort mit Threadsicherheit bereits ausgiebig beschäftigt hat :)

Ansonsten zwei Dinge:
1) Dein LoggingController ist ein Singleton, aber die
Code:
getSharedInstance()
selbst ist nicht threadsicher. Es kann also durchaus sein, dass zwei "sharedinstance" erzeugt werden, wenn die
Code:
getSharedInstance()
gleichzeitig aufgerufen wird (eine Lösung gibts hier: Singleton pattern - Wikipedia, the free encyclopedia).

2) Dann müsste es schon helfen, die Methode
Code:
addSystemLogEntry()
als synchronized zu deklarieren.

3) (...ja ich weiß...) Dein String[][] Feld sieht nach eine Map aus... vielleicht kannst du hier eine HashMap nehmen und die Arbeit wird etwas einfacher? Ich habe es mir aber inhaltlich nicht genauer angeschaut, nur eine Idee.
 

Ähnliche Java Themen

Neue Themen


Oben