Muss ein thread aktive mit stop beendet werden?

  • Themenstarter Themenstarter n00bie
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
N

n00bie

Gast
oder beendet sich der thread von selbst, wenn der code darin 1malig ausgeführt wurde?

und warum ist thread.stop() deprecated? Was ist die Ersatzmethode dafür? mein eclipse 3.3 zeigt mir die .stop() methode durchgestrichen an.
 
Die run-Methode wird EIN mal ausgeführt. Häufig ist dort aber eine "Endlosschleife" drin. Wenn man den Thread vorzeitig beenden will, muss man eine "Notbremse" in die Schleife einbauen. Das kann entweder ein boolean sein, der von außen gesetzt und dann abgefragt wird
Code:
class MyThread extends Thread 
{
    private boolean killed = false;
    public void killHim()
    {
        killed = true;
    }
    public void run()
    {
        while(true)
        {
            System.out.println("All work and no play maked jack a dull boy");

            if (killed)
            {
                break;
            }
        }
    }
}

// Stoppen:
myThread.killHim();
oder man wartet innerhalb des Threads, und fängt dann eine InterruptedException
Code:
class MyThread extends Thread 
{
    public void run()
    {
        while(true)
        {
            System.out.println("All work and no play maked jack a dull boy");

            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException e)
            {
                break;
            }
 
        }
    }
}

// Stoppen:
myThread.interrrupt();
 
"stop" ist deprecated, weil diese Methode Objekte dadurch beschädigen kann,
daß sie in einem nicht koherenten Zustand gelassen werden.
Meistens wird "stop" durch Code ersetzt, der einfach nur eine Variable verändert, um anzuzeigen,
daß der Thread stoppen soll. Der Thread muss diese Variable regelmässig prüfen
und die run-Methode auf geordnete Art verlassen, wenn die Variable anzeigt, daß er stoppen soll.
Es wird empfohlen, diese Variable als "volatile" zu deklarieren.
Daraus folgt, daß ein Thread stirbt, sobald er die run-Methode verlässt.
 
Wenn ich in einem Thread 2 oder n .exe programme aufrufe, muss dann jeder Aufruf in einen eigenen thread?
 
Code:
public void run()
    {
        while(true)
        {
            System.out.println("All work and no play maked jack a dull boy");

            if (killed)
            {
                break;
            }
        }
    }

danke Marco für dein gutes Beispiel! 1 Frage dazu habe ich noch:

Wenn dies:
System.out.println("All work and no play maked jack a dull boy");
der Aufruf einer .exe datei wäre und diese etwas berechnet oder ausführt. Wie kann ich das berechnen denn unterbrechen, wenn das Unterbrechen selber if(killed) erst abgefragt wird, nach dem du System.out.printl aufgerufen hast bzw. bzw. wenn die berechnung mit meinem programm beendet ist?? Das ist mir schleierhaft.
 
Mir auch :wink: Der Aufruf einer EXE-Datei ist schon ein Sonderfall. ("Sowas macht man doch nicht :noe:" :wink: )

Mit Runtime.exec erhält man ja einen Process. Und der hat eine Methode "destroy". Ob der Aufruf dieser Methode den gewünschten Effekt hat (und das kann man nicht sagen: Vielleicht hat die EXE ja inzwischen einen Reset verursacht :wink: ) kann man wohl kaum sagen, ohne es ausprobiert zu haben.
 
Marco13 hat gesagt.:
Mir auch :wink: Der Aufruf einer EXE-Datei ist schon ein Sonderfall. ("Sowas macht man doch nicht :noe:" :wink: )

Mit Runtime.exec erhält man ja einen Process. Und der hat eine Methode "destroy". Ob der Aufruf dieser Methode den gewünschten Effekt hat (und das kann man nicht sagen: Vielleicht hat die EXE ja inzwischen einen Reset verursacht :wink: ) kann man wohl kaum sagen, ohne es ausprobiert zu haben.

hm weiß jetzt nicht ob du mich verstanden hast. WArum darf ich aus java kein kommanozeilen programm aufrufen?

Code:
public class ZipThread extends Thread
	{
		private boolean killed = false;
	    
		public void killZip()
	    {
	        killed = true;	        
	    }
	    public void run()
	    {
	        while(!isInterrupted())
	        {
	           try{	        	    	           
		        	Process p = Runtime.getRuntime().exec("7zip.exe");
		        	if (killed)
		            {
		                p.destroy();
		            	break;
		            }
	              }
	           
	           catch(Exception e)
	           {
	        	   interrupt();
	        	   System.out.println( "Thread wurde beendet");	        	   
	           }
	        }
	    }	
	}

wenn ich von aus nun
Code:
mythread.killZip();
aufrufen würde, würde dann der process p beendet und durch das break die runmethode verlassen UND der Thread beendet?
 
Natürlich "darfst" du ein Kommandozeilenprogramm aufrufen. ("Ich bin anti-autoritär erzogen worden, ich darf ALLES 😎 " :wink: Es macht halt die Plattformunabhängigkeit kaputt - d.h. man sollte sich schon genau überlegen, was man dort macht.

Aber zur eigentlichen Frage: Du willst ja nicht den Java-Thead beenden, sondern den Prozess, den du gestartet hast. Ich habe diesen Fall selbst noch nicht gehabt, darum nur die spontane Idee, dass das mit process.destroy() ja vielleicht gehen könnte - also, ich würde es mal so versuchen, ohne Garantie, dass es klappt (bei einem kurzen Test hätte ich ein Fenster geöffnet, das nicht aufgegangen ist - aber Killen konnte man es ...)

Code:
public class ZipThread extends Thread
{
    public static void main(String args[])
    {
        ZipThread t = new ZipThread();
        t.start();
        System.out.println("Started");
        try
        {
            Thread.sleep(1000);
        }
        catch(InterruptedException e)
        {
        }

        t.killZip();

    }

    private Process process = null;

    public void killZip()
    {
        if(process != null)
        {
            process.destroy();
            System.out.println("process destroyed");
        }
    }

    public void run()
    {
        System.out.println("run");
        try
        {
	        process = Runtime.getRuntime().exec("7zip.exe");
		}
        catch(java.io.IOException e)
        {
            System.out.println("error");
        }
        try
        {
            System.out.println("waiting for process");
            process.waitFor();
        }
        catch(InterruptedException e)
        {
            System.out.println("waiting interrupted");
        }
    }
}
 
Code:
try
        {
            System.out.println("waiting for process");
            process.waitFor();
        }
        catch(InterruptedException e)
        {
            System.out.println("waiting interrupted");
        }

für was benutzt du die methode process.waitFor(); hier nachdem du die zip.exe aufgerufen hast?
 
noobie hat gesagt.:
für was benutzt du die methode process.waitFor(); hier nachdem du die zip.exe aufgerufen hast?

Da Java üblicherweise nicht auf die Beendigung eines exec-Aufrufs wartet.
Ansonsten wäre die run-Methode gleich nach Aufruf von exec() beendet.
 
Leroy42 hat gesagt.:
noobie hat gesagt.:
für was benutzt du die methode process.waitFor(); hier nachdem du die zip.exe aufgerufen hast?

Da Java üblicherweise nicht auf die Beendigung eines exec-Aufrufs wartet.
Ansonsten wäre die run-Methode gleich nach Aufruf von exec() beendet.

Sorry, aber ich verstehe deine Antwort auf meine Frage nicht Also wird das waitfor aufgerufen, damit die 7zip.exe etwas packen kann und nicht gleich beendet wird?
 
Nein!

Das via exec aufgerufene Programm wird unabhängig gestartet
und das Java-Programm läuft einfach weiter also wartet nicht
auf Beendigung des aufgerufenen Programms.

Wenn es doch auf Beendigung warten soll, muß man die
Methode waitFor aufrufen.
 
Die 7zip würde dann "im Hintergrund", "eigenständig" weiterlaufen, während Java mit seiner normalen Ausführung weitermacht. Wenn z.B. "count.exe" ein Programm wäre, das langsam bis 3 zählt, dann würde ein Code wie
Code:
public void run()
    {
        System.out.println("run");
        try
        {
           process = Runtime.getRuntime().exec("count.exe");
       }
       catch(java.io.IOException e){}
       System.out.println("Java hat den Aufruf gemacht, run() ist fertig!");
    }
vielleicht bwirken, dass die folgende Ausgabe erscheint:
run
1
Java hat den Aufruf gemacht, run() ist fertig!
2
3

Dagegen wäre die Ausgabe in diesem Fall
Code:
public void run()
    {
        System.out.println("run");
        try
        {
           process = Runtime.getRuntime().exec("count.exe");

           process.waitFor();
       }
       catch(Exception e){}
        
       System.out.println("Java hat den Aufruf gemacht, der prozess ist beendet, run() ist fertig!");
    }

immer (d.h. sofern der Prozess nicht mit process.destroy() unterbrochen wird)

run
1
2
3
Java hat den Aufruf gemacht, der prozess ist beendet, run() ist fertig!
 
super habs kapiert, waitFor macht den process zuende und erst danach gehts im thread weiter. Danke dir.
 
Aber zur eigentlichen Frage: Du willst ja nicht den Java-Thead beenden, sondern den Prozess

Ich will den Prozess im Thread beenden und den Thread selbst auch , da nach dem aufruf der 7zip.exe noch code kommt wie abfrage wie weit der Komprimierungsvorgang ist etc und stelle dies in einer JProgressBar dar...
 
So sieht der Vorgang aus, wenn ich die 7zip.exe aufrufe und den process beende(7zip.exe ist im task manager entfernt)

Started
waiting for process
process destroyed

Wenn ich danach aber sofort den abgebrochenen Komprimierungsvorgang nochmals probieren möchte mit anderen einstellungen und auf den Komprimierbutton drücke, dann passiert nix(kein 7zip.exe erscheint im task manager) nur diese Ausgabe bekommme ich:

Started
waiting for process

Warum wird die 7zip.exe nicht ein 2.mal aufgerufen?

mein code:

Code:
public void actionPerformed(ActionEvent e)
{    	  
	      if(e.getSource().equals(packBT))
	      {
	           try
	           {
	             meinThread = new PackThread();
	             meinThread.start(); 
	             System.out.println("Started");	             
	             
	           }
	           catch(Exception a)
	           {
                         a.printStackTrace();
                   }
	           meinThread.killZip();
	           
	      }
	      
	      if(e.getSource().equals(stopBT))
	      {
	    	 meinThread.killZip();	    	  
	      }
}

Code:
public class PackThread extends Thread
     {
        
    	 private Process p = null; 
    	 
    	PackThread()
        {       	         	 
        }
        
        
        public void killZip()
        {
            if(p != null)
            {
               p.destroy();
                System.out.println("process destroyed");
            }
        } 
        
        public void run()
        {                     
            
            try
            {   
           	   p = Runtime.getRuntime().exec("7zip.exe");
           	           	  
            }
            catch(java.io.IOException e)
            {
                System.out.println("error");
            }
            try
            {
                System.out.println("waiting for process");
                p.waitFor();
            }
            catch(InterruptedException e)
            {
                System.out.println("waiting interrupted");
            } 
        }
     }
 
gerade ist mir aufgefallen, dass die 1. 5mb datei gepackt wird aber die 2. datei bei 1 kb hängen bleibt und im task manager hat die 7zip.exe nur 0 % cpu auslastung sprich an dem 1 kb ändert sich auch nix mehr.
 
hat sich geklärt mein Schuld mit dem 1kb und hängen bleiben, habe zufällig killzip() aufgerufen nach dem Process p = etc... ;P
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben