# Simpler Thread lässt sich NIE über interrupt() unterbrechen



## jollyroger (26. Feb 2007)

Hallo zusammen, 

ich komme gerade wirklich nicht weiter und hoffe, jemand hier kann mir helfen.....

Ich habe folgenden einfachen Thread als Singleton implementiert:


```
public class MonitorRunner extends Thread {

	private static Logger logger = Logger.getLogger(MonitorRunner.class);
	private static MonitorRunner monRunner = null;
	
	/**
	 * the "main"-method of the monitor, started by Thread.start()
	 */
	@Override
	public void run() {

		logger.info("starting monitoring....");
	
			while(! isInterrupted()) {
				
				/* 		1.) activity cycle		*/
				// for every directory
				for(Iterator i = ConfConstants.SRC_DIRS.iterator(); i.hasNext();) {
					// TODO: implement functionality
				}
				/* 		2.) quiet cycle			*/
				try {
					logger.debug("putting thread to sleep....");
					TimeUnit.SECONDS.sleep(ConfConstants.INT_CHECK_DIRS);
				} catch (InterruptedException e) {
					logger.debug("received interrupt signal while sleeping!");
					logger.debug(e.getMessage());
					logger.debug("stacktrace", e);
					// internal interrupt flag gets reseted by the InterruptedException
					// so we have to interrupt() again
					interrupt();
				}			
			}
	}
	
	public static MonitorRunner getMonRunner() {
		if(monRunner == null) 
			monRunner = new MonitorRunner();
		return monRunner;
	}
	
	private MonitorRunner () {}

}
```

Den versuche ich nun folgendermaßen zu stoppen:



```
private String stopMonitoring() {

		String output = "";
		output += "Attempted to stop monitoring:
";
		logger.debug("Trying to stop monitoring thread....");
		//check if thread is already stopped, alternative to isAlive():Thread.State tState = fileMon.getState();
		if(!MonitorRunner.getMonRunner().isAlive()) {
			output += "Monitoring had already been stopped!
";
			logger.debug("Thread was already stopped");
			return output;
		} 
		// if it is alive, ask the thread to stop in a nice way...
		logger.debug("trying to stop thread via interrupt()");
		MonitorRunner.getMonRunner().interrupt(); 
		Thread.State state = MonitorRunner.getMonRunner().getState(); 
		logger.debug("Thread-state: " + state.toString());
		
		// check if thread is still alive	
		if(MonitorRunner.getMonRunner().isAlive()) {	
			logger.info("could not stop thread via interrupt()!");
			output += "could not stop thread via interrupt()!";
			return output;
		}	
		// if we came so far, thread was terminated normally
		output += "Monitoring is stopped!";
		logger.info("Monitoring thread was stopped!");
		
		return output;
	}
```

So nun ist die log-Ausgabe von stopMonitoring immer die folgende:



```
Trying to stop monitoring thread....
trying to stop thread via interrupt()
Thread-state: RUNNABLE
could not stop thread via interrupt()!
```

Kann mir bitte jemand verraten was da schiefläuft?

Danke für alle Tips!


----------



## Leroy42 (26. Feb 2007)

Du mußt dem Thread nach Aufruf von interrupt() auch die Zeit
geben, die Abfrage isInterrupted zu erreichen.

_Unmittelbar_ nach Aufruf von interrupt() steckt er mit
ziemlicher Sicherheit noch in der sleep-Methode.


----------



## jollyroger (26. Feb 2007)

Hallo, 

daran lag es nicht, ich Genie hatte in 


```
while(! isInterrupted()) {
            
            /*       1.) activity cycle      */
            // for every directory
            for(Iterator i = ConfConstants.SRC_DIRS.iterator(); i.hasNext();) {
               // TODO: implement functionality
            }
```

ein


```
i.next();
```

vergessen und tatsächlich ein Endlosschleife produziert........*kopf gegen die wand hau*


Aber vielen Dank für den Tip von dir, der hat nämlich eine andere Frage geklärt....


Nun hätte ich aber noch eine 2 Fragen (sorry für soviel Nerverei...  )

1.

Hab ich denn noch eine andere Möglichkeit, der Methode, die den Thread unterbrechen will zu sagen: "warte mit der weiteren Ausführung, bis der Thread wirklich fertig ist"

außer sowas zu machen wie:


```
myThread.interrupt();

while(! myThread.getState().toString().equals(Thread.State.TERMINATED)) {
// do nothing, just wait
}
```

oder halt sowas unschönes wie


```
Thread.sleep(1000)
```

zu machen und zu hoffen, das der Thread dann fertig ist?

Ich hab in der Thread-API-Doku nichts entsprechendes gefunden, also muss ich wohl die 1. Möglichkeit nehmen?

2.

Das folgende Problem hab ich gelöst, aber ich weiss nicht warum das so nicht geht:

Also, wenn ich denn Thread so wie stoppe (um den Tip erweitert, dh. Thread.sleep(1000) nach interrupt()):


```
private String stopMonitoring() {

		String output = "";
		output += "Attempted to stop monitoring:
";
		logger.debug("Trying to stop monitoring thread....");
		//check if thread is already stopped, alternative to isAlive():Thread.State tState = fileMon.getState();
		if(!MonitorRunner.getMonRunner().isAlive()) {
			output += "Monitoring had already been stopped!
";
			logger.debug("Thread was already stopped");
			return output;
		} 
		// if it is alive, ask the thread to stop in a nice way...
		logger.debug("trying to stop thread via interrupt()");
		MonitorRunner.getMonRunner().interrupt(); 

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		logger.debug("Thread-state: " + MonitorRunner.getMonRunner().getState().toString());
		// check if thread is still alive	
		if(MonitorRunner.getMonRunner().isAlive()) {	
			logger.info("could not stop thread via interrupt()!");
			output += "could not stop thread via interrupt()!";
			return output;
		}	
		// if we came so far, thread was terminated normally
		output += "Monitoring is stopped!";
		logger.info("Monitoring thread was stopped!");
		
		return output;
	}
```

wird der Thread gestoppt, soweit also ok....

Versuche ich ihn allerdings dann wieder über restartMonitoring bzw. startMonitoring() (restartMonitoring() ruft startMonitoring() auf) wieder anzuschmeissen:


```
/**
	 * restartMonitoring() tries to restart the monitoring thread
	 * @return success or failure message
	 */
	
	private String restartMonitoring() {

		String output = "";
		output += "Attempted to restart monitoring:
";
		logger.info("Trying to restart monitoring thread....");
		//check if thread is already started, alternative to isAlive():Thread.State tState = fileMon.getState();
		if(MonitorRunner.getMonRunner().isAlive()) {
			output += "Monitoring is already up!
";
			logger.info("monitoring thread is already running!");
			return output;
		} 
		// if it is not alive, try to  start the thread
		startMonitoring();
		// check if it is alive
		if(!MonitorRunner.getMonRunner().isAlive()) {
			output += "Monitoring could not be restarted!
";
			logger.error("Monitoring could not be restarted!");
			return output;
		} 
		output += "Monitoring was restarted!
";
		logger.info("Monitoring was restarted!");
		return output;
	}

	/**
	 * startMonitoring() tries to start the monitoring thread
	 */

	private void startMonitoring() {

		// start monitoring thread
		logger.info("starting MonitorRunner...");
		logger.info("thread state: " + MonitorRunner.getMonRunner().getState().toString());
		MonitorRunner.getMonRunner().start();
		
	}
```

Erhalte ich folgende Ausgabe:


```
[http-8180-Processor25]  - thread state: TERMINATED
Feb 26, 2007 7:52:32 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Sender threw exception
java.lang.IllegalThreadStateException
	at java.lang.Thread.start(Thread.java:571)
	at startMonitoring(Sender.java:220)
	at restartMonitoring(Sender.java:179)
```

Die Stelle an der er letztendlich abschmiert, ist die hier aus startMonitoring():



```
MonitorRunner.getMonRunner().start();
```

Bau ich aber nun in meine stopMonitoring()-Methode noch diesen Aufruf mit ein (Rot-Markierung in Code-Tags scheint nicht zu gehen, deshalb mit /********/ markiert) :


```
private String stopMonitoring() {

		String output = "";
		output += "Attempted to stop monitoring:
";
		logger.debug("Trying to stop monitoring thread....");
		//check if thread is already stopped, alternative to isAlive():Thread.State tState = fileMon.getState();
		if(!MonitorRunner.getMonRunner().isAlive()) {
			output += "Monitoring had already been stopped!
";
			logger.debug("Thread was already stopped");
			return output;
		} 
		// if it is alive, ask the thread to stop in a nice way...
		logger.debug("trying to stop thread via interrupt()");
		MonitorRunner.getMonRunner().interrupt(); 

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		logger.debug("Thread-state: " + MonitorRunner.getMonRunner().getState().toString());
               [/********/
                MonitorRunner.getMonRunner().stopThread();
               /********/
		// check if thread is still alive	
		if(MonitorRunner.getMonRunner().isAlive()) {	
			logger.info("could not stop thread via interrupt()!");
			output += "could not stop thread via interrupt()!";
			//MonitorRunner.getMonRunner().stopThread();
			return output;
		}	
		// if we came so far, thread was terminated normally
		output += "Monitoring is stopped!";
		logger.info("Monitoring thread was stopped!");
		
		return output;
	}
```

stopThread() ist in meiner Thread-Klasse folgendermaßen implementiert:


```
public class MonitorRunner extends Thread {

	private static Logger logger = Logger.getLogger(MonitorRunner.class);
	private static MonitorRunner monRunner = null;
	
	/**
	 * the "main"-method of the monitor, started by Thread.start()
	 */
	@Override
	public void run() {

		logger.info("starting monitoring....");
		checkConfiguration();
		logger.info("starting monitoring....");
		
			while(! isInterrupted()) {
				
				/* 		1.) activity cycle		*/
				// for every directory
				for(Iterator i = ConfConstants.SRC_DIRS.iterator(); i.hasNext();) {
					// TODO: implement functionality
					i.next();
				}
				/* 		2.) quiet cycle			*/
				try {
					logger.debug("putting thread to sleep....");
					TimeUnit.SECONDS.sleep(ConfConstants.INT_CHECK_DIRS);
				} catch (InterruptedException e) {
					logger.debug("received interrupt signal while sleeping!");
					logger.debug(e.getMessage());
					logger.debug("stacktrace", e);
					// internal interrupt flag gets reseted by the InterruptedException
					// so we have to interrupt() again
					interrupt();
				}			
			}

	}
	
	private void checkConfiguration() {
		// check if only directories were given
		
	}

	public static MonitorRunner getMonRunner() {
		if(monRunner == null) 
			monRunner = new MonitorRunner();
		return monRunner;
	}
	
	private MonitorRunner (){	}

        /********/
        public void stopThread() {
		monRunner = null;
	}
}
```

Dann klappt das Ganze, sprich ich kann den Thread restarten???

Also lange Rede kurzer Sinn:

Ich kann auf einem Thread des state == TERMINATED ist, kein start() mehr aufrufen?

Bin ich jetzt blind, oder warum sehe ich in der API-Doku nichts dazu?


----------



## jollyroger (26. Feb 2007)

jollyroger hat gesagt.:
			
		

> Hallo,
> 
> daran lag es nicht, ich Genie hatte in
> 
> ...


----------



## Marco13 (27. Feb 2007)

Ohne jetzt den ganzen Code gelesen (oder sogar nachvollzogen) zu haben:


			
				jollyroger hat gesagt.:
			
		

> Ich kann auf einem Thread des state == TERMINATED ist, kein start() mehr aufrufen?


Ja.


			
				jollyroger hat gesagt.:
			
		

> Bin ich jetzt blind, oder warum sehe ich in der API-Doku nichts dazu?


Vielleicht weil du nicht bei "Thread.start()" gelesen hast :wink:
_ It is never legal to start a thread more than once._


----------



## jollyroger (27. Feb 2007)

> Vielleicht weil du nicht bei "Thread.start()" gelesen hast icon_wink.gif
> It is never legal to start a thread more than once.



Ja, 

das muss ich wirklich überlesen haben..... :wink: 

Danke dir!


----------



## Illuvatar (27. Feb 2007)

Zur ersten Frage:

thread.join();


----------



## jollyroger (28. Feb 2007)

Hallo und vielen Dank für die Klarstellung..... :wink: 

Eine Verständnisfrage noch:


```
myThread.interrupt();
myThread.join();
```

ist doch eigentlich genau das Gleiche wie


```
myThread.interrupt();

while(! myThread.getState().toString().equals(Thread.State.TERMINATED)) {
// do nothing, just wait
}
```

?


----------



## Leroy42 (28. Feb 2007)

An sich schon, aber du würdest deine Prozessorlast unnötig
auf 100 % hochschnallen lassen, wenn du in deine while-Schleife
kein sleep einbaust.


----------

