Unbeschaeftigten Thread in einer Schleife schlafen legen? Schlechter Stil?

sirbender

Top Contributor
Hi,

ich habe einen Thread den ich ab und zu etwas machen lasse. Wenn er nichts zu tun hat schlaeft er kurz in einer Schleife:

Java:
				while (isPaused == true) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e1) {
						e1.printStackTrace();
					}
				}

Ist das wie ich das mache schlechter Stil? Wie wuerdet Ihr es machen? Vielleicht will ich die Anwendung bald aufs Handy portieren. Da hat Schludrigkeit mit Threads leichter Auswirkungen. Auf dem Dektop kann man viel falsch machen ohne dass man einen Unterschied merkt.

Danke,
sb
 
Starte den Thread mit einer bestimmten Aufgabe. Wenn er damit fertig ist beendet sich der Thread. Wenn du dann wieder was zu tun hast startest du nen neuen mit der neuen Aufgabe.
 
Genau das meinte ich mit Smartphone-Thread-Aufwand. Wenn ich mich nicht irre sollte man nicht tonnenweise Threads erstellen, diese beenden lassen und dann neue erstellen. Irgendwo hab ich mal gelesen, dass dies auf einem Smartphone Gift fuer die Performance ist, da der Aufwand einen neuen Thread zu erstellen im Vgl. zum Desktop ungemein hoeher ist.
 
Keine Ahnung, kann schon dass das bei Smartphones so ist, da kenn ich mich nicht aus. Auf jedenfall isses aber wohl sauberer wenn du Threads beendest wenn die fertig sind.
 
Benutze einen ExecutorService. Da kann es dir egal sein, wie der das intern mit den Threads handhabt - wenn es auf dem Smartphone zu langsam ist, weil deine Informationen stimmen (was ich nicht weiß), kannst du immer noch eine anderen Executor und damit eine andere Thread-Erstellen-und-Vernichten-Strategie wählen. Und zwar durch nur eine einzige Code-Änderung.

Das was du jetzt gerade machst ist jedenfalls nicht gut, weil der Thread permanent Rechenzeit braucht (busy-waiting).
 
Ist es wirklich busy-waiting wenn der Thread fuer 100ms schlaeft?

Jep... Aber statt Threads zu beenden oder busy waiting, kann man sie auch anders schlafen legen.
Java:
interface Work {
   doWork();
}

class Worker extends Thread {
  private final Lock lock = new Lock();

  public void run() {
    while(!isInterrupted()) {
      synchonized(lock) {
        if(lock.work != null) {
          lock.work.doWork();
          lock.work = null;
          synchronized(this) {
            try {
              wait();
            } catch(InterruptedException ie) {
              interrupt();
            }
          }
        }
      }
    }
  }

  public void doWork(Work work) {
    if(work == null) {
      return;
    }
    synchronized(lock) {
      if(lock.work == null) {
        lock.work = work;
      }
      notify();
    }
  }

  private class Lock {
    Work work;
  }
}
 
DU kanst doch eine
Java:
java.util.concurrent.BlockingQueue<E>

Verwenden, um den Thread seine Aufgaben zu geben.
Die Aufgaben würde ich dann als Interface implementieren:
Java:
public interface IWork 
{
    public void work() throws Exception;
    public void finish();
    public void exception(final Exception e);
}

Der Thread kann dann so arbeiten:
Java:
public final class WorkThread extends Thread
{
    private final BlockingQueue<IWork> work;
    private boolean run = true;
    public WorkThread()
    {
        this.work = new LinkedBlockingQueue<IWork>();
        setName("WorkThread");
        setPriority(Thread.MIN_PRIORITY);
        setDaemon(true);
        start();
    }
    
    public synchronized boolean addWork(final IWork iWork)
    {
        return this.work.offer(iWork);
    }
    
    public synchronized void finish()
    {
        this.work.clear();
        this.work.add(new IWork() {
            
            @Override
            public void work() throws Exception {
            }
            
            @Override
            public void finish() {
            }
            
            @Override
            public void exception(Exception e) {
            }
        });
        this.run = false;
    }
    
    @Override
    public void run() 
    {
        while(run)
        {
            try 
            {
                final IWork iWork = this.work.take();
                try
                {
                    iWork.work();
                    iWork.finish();
                }
                catch(Exception e)
                {
                    iWork.exception(e);
                }
            } 
            catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
 

Zurück
Oben