Java erzeugt zu viel Last?

Status
Nicht offen für weitere Antworten.

Paat

Aktives Mitglied
Hi,

ich habe eine kleine Java Applikation geschrieben, die auf einem UNIX Server läuft (AIX 6.1)

Java:
public static void main(String[] args) {
		
		createLog(log); //Überpruft ob die Logdatei erxistiert, wenn nicht wird sie angelegt
		startApplication(); //Startet 12 Threads, welche Daten an eine Datenbank schicken. Diese Schicken aber nur alle 5 Minuten etwas und erzeugen deshalb nur 5 Minuten ein wenig last
		

		File stopFile = new File(baseDirBin + "stop");
		
		while(true){
			if(stopFile.exists()) {
				
				setStatus(false);
				System.out.println("The Appication was requested to stop. Please wait until you get a message.");
				stopFile.delete();
				try {
				Thread.currentThread().sleep(500000);
				System.out.println("Application successfully stopped!");
				exit();
				}catch(Exception e){
					System.exit(1);
				}
				
			}
			
			try{
				Thread.currentThread().sleep(20000);
			}catch(Exception e){
				System.out.println("Fehler beim main sleep: " + e);
			}
			
			
		}
	
	}

Das Programm läuft auf einer p520 mit 2 POWER6 Prozessoren (jeweils 4,2 GHZ Dual Core) und lastest das System zu 50 % aus. Das heißt es braucht im Durchschnitt einen Prozessor und zwar durchgehend.

Hinter der Prozess ID, die die ganze Last erzeugt, versteckt sich die jar Datei die ausgeführt wird.

Nur was in der main Methode erzeugt die ganze Last? Oder braucht der für die Threadverwaltung die ganze Power?
 
if(stopFile.exists())
Wenn stopFile eben nicht existiert, dann tut die Schleife gar nichts. Das heißt du verbrätst eine CPU um immer wieder while(true) zu prüfen.

EDIT: ah, da unten kam noch ein sleep das noch zur Schleife gehört.
Einer deiner anderen Threads tut dann wohl mehr als du denkst. Profiler helfen bei sowas.
 
Hmne.. da steht ja noch ein
Thread.currentThread().sleep(20000);
Eigentlich sollte das Programm ohnehin die meiste Zeit über garnichts machen ... ???:L Läauft da noch irgendwo ein anderer Thread?
 
yo das sleep 20 habe ich extra in die While Schliefe reingepackt. Vorher brauchte das Programm beide Prozessoren.


Sonst läufen nur die 12 Threads, die dann als eigene Prozesse aufgeführt werden und die meiste Zeit 0 % last brauchen.
 
Jo, die entscheidende Frage ist eben, ob diese 12 Threads wirklich laufen oder die meiste Zeit nur schlafen... Ist das, was diese 12 Threads machen, wirklich mit sleeps und/oder wait/notify so geregelt, dass sie "nichts" tun? Also, geht die Prozessorlast wirklich auf ca. 0 runter, wenn du NUR diese 12 Threads startest und den geposteten Code ansonsten auskommentierst?
 
OK hier weiterer Code


Die Methode createLogFile()
Java:
public static void createLog(File log) {
		
		if(!log.exists()){
			try {
				log.createNewFile();
			}catch(IOException e){
				System.out.println("Fehler1: " + e);
				System.exit(1);
			}
		}
	}


Die Methode startApplication()

Java:
public static void startApplication() {
		setStatus(true);
		
		try {

		Runnable r4101 = new TaskRunnerDS4101();
		Runnable r4102 = new TaskRunnerDS4102();
		Runnable r4103 = new TaskRunnerDS4103();
		//Runnable r4301 = new TaskRunnerDS4301();
		Runnable r4302 = new TaskRunnerDS4302();
		Runnable r4303 = new TaskRunnerDS4303();
		Runnable r4304 = new TaskRunnerDS4304();
		//Runnable r4305 = new TaskRunnerDS4305();
		//Runnable r4306 = new TaskRunnerDS4306();
		Runnable r4701 = new TaskRunnerDS4701();
		Runnable r4702 = new TaskRunnerDS4702();
		Runnable r4703 = new TaskRunnerDS4703();
		Runnable r4704 = new TaskRunnerDS4704();
		Runnable r4705 = new TaskRunnerDS4705();
		Runnable r5101 = new TaskRunnerDS5101();
		Runnable r5102 = new TaskRunnerDS5102();
		Runnable r4305lun = new TaskRunnerDS4305LUN();
		Runnable r4306lun = new TaskRunnerDS4306LUN();
		
		Thread thr4101 = new Thread(r4101);
		Thread thr4102 = new Thread(r4102);
		Thread thr4103 = new Thread(r4103);
		//Thread thr4301 = new Thread(r4301);
		Thread thr4302 = new Thread(r4302);
		Thread thr4303 = new Thread(r4303);
		Thread thr4304 = new Thread(r4304);
		//Thread thr4305 = new Thread(r4305);
		//Thread thr4306 = new Thread(r4306);
		Thread thr4701 = new Thread(r4701);
		Thread thr4702 = new Thread(r4702);
		Thread thr4703 = new Thread(r4703);
		Thread thr4704 = new Thread(r4704);
		Thread thr4705 = new Thread(r4705);
		Thread thr5101 = new Thread(r5101);
		Thread thr5102 = new Thread(r5102);
		Thread thr4305lun = new Thread(r4305lun);
	Thread thr4306lun = new Thread(r4306lun);
		
		thr4101.start();
		thr4102.start();
		thr4103.start();
		//thr4301.start();
		thr4302.start();
		thr4303.start();
		thr4304.start();
		//thr4305.start();
		//thr4306.start();
		thr4701.start();
		thr4702.start();
		thr4703.start();
		thr4704.start();
		thr4705.start();
		thr5101.start();
		thr5102.start();
		thr4305lun.start();
		thr4306lun.start();
		
		}catch(Exception e){
			System.out.println("Fehler: " + e);
		}
		
	}


Eine exemplarische Klasse Taskrunner DS4101. Die anderen unterscheiden sich nur durch die Parameter. Ich wusste nicht wie es sonst parallelisieren sollte.
Java:
public class TaskRunnerDS4101 implements Runnable, StorageSubsysteme {
	
	public TaskRunnerDS4101(){
		
	}
	
	public void run(){
		
		File datFile = new File(DS4101);
			
			while(StatusGui.getStatus() && datFile.exists()){
			
				DS4000Collector ds4101 = new DS4000Collector(DS4101, "DS4101",DS4101IP1,DS4101IP2);
			}
	}


Hier ist die eigentliche Algorithmik drinn

Java:
public class DS4000Collector {



	public DS4000Collector(String exec, String TABLE,
			String ip1, String ip2) {

		SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss ");
		
		try{
		FileWriter output = new FileWriter(StatusGui.log,true);
		
		try {
			
			InetAddress inet1 = InetAddress.getByName(ip1);
			InetAddress inet2 = InetAddress.getByName(ip2);

			if (inet1.isReachable(5000) && inet2.isReachable(5000)) {

				try {
					DriverManager
							.registerDriver(new oracle.jdbc.driver.OracleDriver());
					String url = "jdbc:oracle:thin:@miscdb:1527:MISC";

					Runtime rtm = Runtime.getRuntime();
					String[][] values;

					Process p = rtm.exec(exec);
					java.util.Date now = new java.util.Date();

					BufferedReader in = new BufferedReader(
							new InputStreamReader(p.getInputStream()));
					String s;

					while ((s = in.readLine()) != null) {

						

						if (s.contains("SMcli failed")) {
							output.write("\n"
											+ formatter.format(now)
											+ ":Unknouw Error Storage-Subsystem "
											+ TABLE);
						}
						
						if(s.contains("TOTALS") || (s.contains("Logical")&& !s.contains("Heartbeat"))){
							values = CSVParser.parse(s);
							
							double kb_sec = Double.parseDouble(values[0][4]);
							double total_io = Double.parseDouble(values[0][6]);
							double read_percentage = Double.parseDouble(values[0][2]);
							double read_io = (int)((total_io * read_percentage / (double)100)*100)/100.0;
							double write_io = (int)((total_io - read_io)*100)/100.0;
							double cache_hits_percentage = Double.parseDouble(values[0][3]);

							if (s.contains("TOTALS")) {
							
							try {
								Connection conn = DriverManager.getConnection(url,
										"de11828", "abc123");
							
								PreparedStatement pstmt = conn
										.prepareStatement("INSERT INTO "
												+ TABLE
												+ " (DATUM,KB_TOTAL,IO_READ,IO_WRITE,CACHE_HIT_PERCENTAGE) VALUES(?,?,?,?,?)");

								pstmt.setTimestamp(1, new java.sql.Timestamp(
										now.getTime()));
								pstmt.setDouble(2, kb_sec);
								pstmt.setDouble(3, read_io);
								pstmt.setDouble(4, write_io);
								pstmt.setDouble(5, cache_hits_percentage);
								ResultSet rset = pstmt.executeQuery();
								
							
								/*output.append(
										"\nTimestamp: " + formatter.format(now) + " | " +
										"Storage-Subsystem: " + TABLE + " | " +
										"Current KB/second: " + kb_sec + " | " +
										"Read IO/second: " + read_io + " | " +
										"Write IO/second: " + write_io + " | " +
										"Cache Hit Percentage: "+ cache_hits_percentage + " | ");*/

								pstmt.close();
								conn.close();				
							} catch (Exception e) {
								output.append("\nDatenbase Exception: " + e
										+ " on " + TABLE + "\n");
							}
							}
						}
					
					}
					p.destroy();
				} catch (Exception e) {
					output.append("\nSMCli Exepction: " + e + " on " + TABLE + "\n");
				}
			} else {
				output.append("\n"
						+ "Could not connect to Storage-Subsystem: "
						+ TABLE + "\n");
			}

		} catch (Exception e) {
			try{
			output.append("\nInet Exception: " + e  + " on " + TABLE + "\n");
			}catch(Exception ioe){
				
			}
		}
		
			output.close();
			
		}catch(IOException e){
			System.out.println("Fehler beim FileWriter: " + e);
		}

	}

}

In dem Prozess der aufgerufen wird wird ein externes Programm gestartet, was 5 Minuten läuft und Performance Werte sammelt und diese auf die Konsole ausgibt. Dann wird der output gefiltert und an die DB geschickt



In den Klassen DS4305LUN und DS4306LUN werden nur etwas andere Werte an die DB geschickt. Von der Algorithmik sind sie genauso wie DS4000Collector
 
Zuletzt bearbeitet:
Ja, das eigentliche Problem ist vermutlich(!)
Code:
 while(StatusGui.getStatus() && datFile.exists()){
            
                DS4000Collector ds4101 = new DS4000Collector(DS4101, "DS4101",DS4101IP1,DS4101IP2);
            }
    }
in der TaskRunnerDS4101: Dort läuft eine while-Schleife eventuell(!) ungebremst... aber bevor du dieses Problem jetzt behebst, solltest du dir DRINGENDST überlegen, wie du die ganze Struktur vernünftig machen kannst: Diese ganzen Runnables und einzelnen Mini-Klassen sind extremst häßlich :autsch:

Ein Ansatz in diese Richtung wäre sowas wie
Code:
public class TaskRunner implements Runnable, StorageSubsysteme {
    
    private String s;
    private String ip1;
    private String ip2;

    public TaskRunner(String s, String ip1, String ip2){
        this.s = s;
        this.ip1 = ip1;        
        this.ip2 = ip2;        
    }
    
    public void run(){
        
        File datFile = new File(s); // oder so
            
            while(StatusGui.getStatus() && datFile.exists()){
            
                Collector collector = new Collector(s, ip1, ip2); // Oder so...

                // hier halt ein sleep oder so, das müßte man nochmal genauer nachsehen..
            }
    }
also ganz allgemein: Die Unterschiede als Parameter an die Klassen übergeben...
 
Kann es sein, das das Java Programm garnicht auf das externe Programm wartet sondern einfach ohne Unterbrechungs weiterläuft? Wenn ja, hast du 12 Unendlichschleifen die ohne Unterbrechung durcharbeiten
 
erstmal danke.

yo die Struktur gefällt mir auch nicht so ganz.


Java:
while(StatusGui.getStatus() && datFile.exists()){
            
                DS4000Collector ds4101 = new DS4000Collector(DS4101, "DS4101",DS4101IP1,DS4101IP2);
            }
    }

wartet der hier nicht bis das, was in dem Objekt passiert beendet ist? Oder ruft der hier unendlich viele Objekte auf?

Bzw. wie kann ich hier sicherstellen dass die while Schliefe wartet bis das Objekt "beende"t ist
?
 
Ihr hattet recht, das ganze läuft dort als Endlosschleife.

wie kann ich hier sichherstellen:

Java:
while(StatusGui.getStatus() && datFile.exists()){
            
                DS4000Collector ds4101 = new DS4000Collector(DS4101, "DS4101",DS4101IP1,DS4101IP2);
            }
    }

dass das nächste Objekt erst erzeugt wird, wenn alles in dem alten abgeschlossen ist?
 
ahhh. So nochmal Kommando zurück.


Ich habe den Fehler gefunden. Also in der While Schleife wird immer gewartet bis alles im Konstruktor des Objektes abgeschlossen ist. Jedoch hatte ich mich bei zwei externen Kommandos vertippt. Dadurch ist die while Schleife in zwei Threads endlos durchgelaufen, was schließlich auch die Last erzeugt hat.

Also danke an alle fürs helfen 😉

@ Marco

Habs auch umgebaut. Hatte die Miniklassen nur gemacht, weil ich nicht wusste wie ich Parameter an die methode run() übergeben sollte. Aber war eigentlich klar, dass es über die Klasse geht.

Vielen Dank an alle
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben