web-dev-qa-db-fra.com

Meilleure façon de créer et d'utiliser une classe Runnable anonyme

Je veux utiliser une classe anonyme pour Runnable. Il y a deux façons, mais je ne sais pas si elles font la même chose ou non:

Première méthode: en utilisant Runnable directement, puis en appelant run():

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

Deuxième méthode: créez un Runnable anonyme et collez-le dans Thread, en utilisant la méthode start() au lieu de run():

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

Je pense que la deuxième méthode est évidemment vraie. Mais, je ne sais pas si cela fait la même chose que la première méthode. Peut-on appeler directement la méthode run() sur un Runnable?

34
hqt

Non, vous n'appelez généralement pas run() directement sur un Runnable car vous n'aurez pas de thread en arrière-plan de cette façon. Si vous ne voulez pas et n'avez pas besoin d'un thread d'arrière-plan, appelez bien run() directement, mais sinon si vous voulez créer un thread d'arrière-plan et exécuter votre Runnable à partir de celui-ci, vous devez créer un nouveau thread puis passez le Runnable dans son constructeur, et appelez start().

En outre, il existe d'autres façons d'accomplir cette tâche, notamment l'utilisation d'exécuteurs et de services d'exécution, et vous devriez en étudier l'utilisation, car ils offrent plus de flexibilité et de puissance que l'utilisation d'un objet Thread bare bones.

Vous voudrez également jeter un œil à l'utilisation de l'interface Future et de la classe FutureTasks qui sont comme Runnables, mais elles vous permettent de retourner un résultat une fois terminé. Si vous avez utilisé un SwingWorker, vous avez déjà utilisé une interface Future sans vous en rendre compte.

Comme les autres l'ont mentionné, l'utilisation de la classe Thread est la bonne façon. Cependant, vous devez également envisager d'utiliser Javas Executors framework pour gérer les threads en cours d'exécution.

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

Bien sûr, il suffit d'utiliser directement Thread. Mais il est généralement conseillé (ou préféré) d'utiliser le framework. Laissez Java gérer les détails fins pour vous.

24
jakson

Votre méthode 1 n'a pas de sens. L'interface Runnable n'a de sens pour le filetage que lorsqu'elle est exécutée dans un Thread (votre méthode 2). Si vous voulez trouver une autre façon d'envelopper en ligne, un morceau de code à l'intérieur d'un thread, cela peut être l'un:

Thread t = new Thread()
{
     public void run()
     {
        // put whatever code you want to run inside the thread here.
     }
};
t.start();
6
ylabidi

Je voudrais ajouter quelque chose à cette discussion (vous avez déjà obtenu de bonnes réponses).
.

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
Yair Zaslavsky

Dans la première méthode, cela fonctionnera comme une méthode en tant qu'interface Runnable implémentant et appelant, mais aucun thread d'arrière-plan ne sera créé. Le fait est que lorsque nous appelons la méthode de démarrage, le thread corrosif commence à s'exécuter, la machine virtuelle Java appelle la méthode d'exécution de ce thread en interne. Donc, pour démarrer un thread, nous devons appeler la méthode de démarrage avec l'interface Runnable refernce. Dans la première méthode, même nous ne pouvons pas appeler la méthode start avec la référence d'interface Runnable car l'interface Runnable ne prend pas en charge la méthode start (). Il est donc obligatoire de créer l'objet de la classe Thread pour démarrer l'exécution du thread.

2
Mohamed Sahil

Rappelez-vous toujours que Runnable est juste un code que vous voulez ou pouvez exécuter dans un thread. Une façon de définir le code Runnable de manière anonyme est:

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

Et puis vous pouvez créer un fil et passer le Runnable que vous avez créé à ce nouveau fil comme celui-ci

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

Après avoir appelé la méthode start () de la classe Thread, le code qui va à l'intérieur de la méthode run () s'exécute sur le thread nouvellement créé.

Vous pouvez également chercher une manière différente de créer un objet Runnable ici

1
Krishna Sapkota

La première manière est fausse: elle ne crée pas de nouveau fil donc elle est inutile.

C'est comme mettre le code en dehors d'un exécutable.

Notez que il y a deux façons de lancer un nouveau thread sur du code défini dans une classe anonyme, comme décrit dans javadoc de Thread mais votre méthode 1 n'en fait pas partie et votre méthode 2 est celle que vous devriez généralement préférer.

1
Denys Séguret

Comme le mentionne @Hovercraft, si vous appelez directement une méthode Runnable.run(), un Thread n'est pas du tout créé. C'est comme appeler n'importe quelle autre méthode (System.out.println(...), ...).

Lorsque vous passez un objet Runnable au constructeur Thread, cela définit le champ target dans le Thread comme votre objet:

this.target = target;

Ensuite, lorsque vous appelez start() sur le Thread, cela fait le travail de forder le nouveau thread et d'appeler la méthode Thread.run(). La fonction Thread.run() appelle tour à tour la méthode run() de la cible:

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

Ainsi, passer le Runnable à un Thread puis appeler start() est la façon d'exécuter votre Runnable en arrière-plan dans un thread séparé.

1
Gray

Votre méthode 1 ne peut généralement pas faire de travail utile. Avec cette méthode, si vous souhaitez obtenir la sortie d'un simple programme HelloWorld.Java, c'est-à-dire "Hello World", il ressemblera au code inutile suivant, mais il affichera "Hello World". Vous devez donc utiliser votre deuxième méthode. Code inutile:

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
Harjit Singh

Voici un exemple de code simple expliquant comment créer correctement une classe Runnable anonyme et gérer la fuite de mémoire (exemple pour Android):

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
0xAliHn