Najlepszy sposób tworzenia i używania anonimowej klasy Runnable

Chcę użyć anonimowej klasy dla runnable. Są dwa sposoby, ale nie wiem czy robią to samo czy nie:

Metoda pierwsza: użycie bezpośrednio Runnable i wywołanie run

new Runnable() {
    @Override
    public void run() {
    }
}.run();

Metoda druga: Utwórz anonimowy runnable i wklej do wątku, używając metody start zamiast run:

new Thread( new Runnable() {
    @Override
    public void run() {
    }
}).start();
Myślę, że metoda druga jest oczywista. Ale nie wiem, czy robi to samo, co metoda pierwsza ? Czy możemy wywołać metodę run bezpośrednio na Runnable ?

Dzięki:)

Author: laish129, 2012-10-07

10 answers

Nie, zwykle nie wywołasz run() bezpośrednio na Runnable, ponieważ nie otrzymasz w ten sposób wątku tła. Jeśli nie chcesz i nie potrzebujesz wątku w tle, to fine wywołaj run() bezpośrednio, ale jeśli chcesz utworzyć wątek w tle i uruchomić Runnable z jego wnętrza, musisz utworzyć nowy wątek, a następnie przekazać Runnable do jego konstruktora i wywołać start().

Istnieją również inne sposoby realizacji tego zadania, w tym Korzystanie z Executorów i usług ExecutorServices, powinieneś przyjrzeć się tym zastosowaniom, ponieważ oferują one większą elastyczność i moc niż używanie obiektu z gwintem bare bones.

Warto również przyjrzeć się wykorzystaniu interfejsu Future i klasy FutureTasks , które są jak Runnables, tylko pozwalają zwracać wynik po zakończeniu. Jeśli używałeś SwingWorker, to już używałeś przyszłego interfejsu, nie zdając sobie z tego sprawy.

 23
Author: Hovercraft Full Of Eels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-07 18:33:33

Jak wspomnieli inni, używanie klasy Thread jest właściwym sposobem. Należy jednak zwrócić uwagę na używanie Javas Executors framework do obsługi uruchomionych wątków.

Executors.newSingleThreadExecutor().execute(new Runnable() {
    @Override 
    public void run() {
        // code in here
    }
});

Oczywiście samo używanie wątku bezpośrednio jest w porządku. Ogólnie jednak zaleca się (lub preferuje) korzystanie z frameworka. Niech Java zajmie się drobnymi szczegółami za Ciebie.

 23
Author: jakson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-07 18:38:05

Twoja metoda 1 nie tworzy sens. Interfejs Runnable ma znaczenie dla wątków tylko wtedy, gdy jest wykonywany wewnątrz Thread (twoja metoda 2). Jeśli chcesz znaleźć inny sposób na zawinięcie fragmentu kodu w wątku, może to być jeden z następujących sposobów:]}

Thread t = new Thread()
{
     public void run()
     {
        // put whatever code you want to run inside the thread here.
     }
};
t.start();
 6
Author: ylabidi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-07 18:37:21

Chciałbym coś dodać w tej dyskusji (masz już dobre odpowiedzi).
Jeśli twój obiekt Runnable jest bezstanowy, w celu zmniejszenia alokacji pamięci (co zajmuje czas + zużywa trochę pamięci - pomyśl o przypadku, w którym aplikacja znacznie korzysta z wątków) - rozważ posiadanie statycznego pola trzymającego obiekt runnable.

private static Runnable runnable = new Runnable() { //Once again - do this only if this is a statelss object!
   public void run() {
   }
} 

//Use the runnable somewhere in the code
 4
Author: Yair Zaslavsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-07 19:42:12

W metodzie pierwszej będzie działać jak Metoda jako implementacja i wywołanie interfejsu Runnable, ale nie zostanie utworzony wątek tła. Faktem jest, że wywołanie metody start powoduje rozpoczęcie wykonywania wątku corrosponding, Wirtualna Maszyna Java wywołuje metodę run tego wątku wewnętrznie . Aby uruchomić wątek musimy wywołać metodę start z refernce Runnable interface . W metodzie pierwszej nawet nie możemy wywołać metody start z runnable interface reference jako Runnable interfejs nie obsługuje metody start (). dlatego obowiązkowe jest utworzenie obiektu klasy Thread, aby rozpocząć wykonywanie wątku .

 2
Author: Mohamed Sahil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-14 18:33:43

Pierwszy sposób jest zły : nie tworzy nowego wątku, więc jest bezużyteczny.

To tak, jakby umieścić kod poza runnable.

Zauważ, że istnieją dwa sposoby uruchomienia nowego wątku na kodzie zdefiniowanym w anonimowej klasie , jak opisano w javadoc w wątku, ale twoja metoda 1 nie jest wśród nich, a twoja Metoda 2 jest tą, którą powinieneś Zwykle preferować.

 1
Author: Denys Séguret,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-07 18:22:40

Jako @ Hovercraft mentionds, jeśli wywołasz metodę Runnable.run() bezpośrednio, Thread nie jest tworzony w ogóle. To tak jak wywołanie dowolnej innej metody (System.out.println(...),...).

Kiedy przekazujesz obiekt Runnable do konstruktora Thread, który ustawia pole target w Thread jako twój obiekt:

this.target = target;

Następnie, gdy wywołujesz start() na Thread, wykonuje to pracę rozwidlenia nowego wątku i wywołania metody Thread.run(). Thread.run() wywołuje z kolei metodę run() celu:

public void run() {
    if (target != null) {
        target.run();
    }
}

Więc przekazanie Runnable do Thread, a następnie wywołanie start() jest sposobem uruchomienia Runnable w tle w oddzielnym wątku.

 1
Author: Gray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-07 18:27:18

Zawsze pamiętaj, że Runnable to tylko kod, który chcesz lub możesz uruchomić w wątku. Jednym ze sposobów na anonimowe zdefiniowanie kodu Runnable jest:

  Runnable codeToRunOnThread=new Runnable() {
      @Override
      public void run() {
      //code to run in a thread you want
      }
  };

A następnie możesz utworzyć wątek i przekazać Utworzony przez Ciebie Runnable do nowego wątku w ten sposób

  Thread myThread=new Thread(codeToRunOnThread);
  myThread.start();

Po wywołaniu metody start() klasy Thread, kod znajdujący się wewnątrz metody run() uruchamia się w nowo utworzonym wątku.

Możesz również wyglądać inaczej tworząc obiekt tutaj

 1
Author: Krishna Sapkota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 14:23:30

Twoja metoda 1 zazwyczaj nie może wykonać żadnej użytecznej pracy. Za pomocą tej metody, jeśli chcesz uzyskać wyjście prostego HelloWorld.program java tj. "Hello World", będzie przypominał poniższy bezużyteczny kod, ale wyświetla "Hello World". Więc powinieneś użyć swojej drugiej metody.

class MyRunnable implements Runnable {

    public void run() { 
    System.out.println("Hello World");
    }

    public static void main(String[]arg){ 
    MyRunnable myRunnable = new NamedRunnable( );
    namedRunnable.run();
    } 
}
 0
Author: Harjit Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-24 15:47:23

Oto prosty przykład kodu, jak poprawnie utworzyć anonimową klasę Runnable i poradzić sobie z wyciekiem pamięci (przykład dla Androida):

public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {

            MyRunnable myRunnable = new MyRunnable(this);
            myHandler.postDelayed(myRunnable, TimeUnits);
}

// Must be declared as a static class    
private static class MyRunnable implements Runnable {
        WeakReference<MainActivity> mActivity;
        // Creating weakreference
        MyRunnable(MainActivity activity) {
            mActivity = new WeakReference<>(activity);
        }

        @Override
        public void run() {
            MainActivity activity = mActivity.get();
            // Checking reference exist or not
            if (activity != null) {
                    //Do necessary tasks
                }
            }
        }
    }

}
 0
Author: 0xalihn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-31 11:44:52