web-dev-qa-db-fra.com

Quelle est la différence entre Handler, Runnable et Threads?

Quelle est la différence entre Handler, Runnable et Threads?

Pendant que je travaillais avec Android, j'ai besoin de quelque chose pour fonctionner en arrière-plan. J'utilise Threads pour l'exécuter. Habituellement, j'écrivais une classe qui étend Thread et implémentait la méthode run.

J'ai également vu quelques exemples qui implémentent runnable et passent dans runnable dans Threads.

Cependant, je suis toujours confus. Quelqu'un peut-il me donner une explication claire?

  1. Quel est l'intérêt de Runnable si l'on peut écrire le code d'arrière-plan dans la méthode d'exécution du thread?
  2. Comment le gestionnaire est-il utilisé à l'intérieur du fil et pourquoi devons-nous l'utiliser.
  3. Android a une autre chose appelée runOnUiThread, comment utilisons-nous cela? Je sais qu'il est utilisé pour mettre à jour l'interface utilisateur.
30
Hong Wei Wang

Pourquoi utiliser Runnable sur Thread?

  • Runnable sépare le code qui doit s'exécuter de manière asynchrone de comment le code est exécuté. Cela maintient votre code flexible. Par exemple, le code asynchrone dans une exécutable peut s'exécuter sur un pool de threads ou un thread dédié.

    Un Thread a indiqué que votre exécutable n'a probablement pas besoin d'accéder à. Avoir accès à plus d'état que nécessaire est une mauvaise conception.

    Les threads occupent beaucoup de mémoire. La création d'un nouveau thread pour chaque petite action prend du temps de traitement pour allouer et désallouer cette mémoire.

Que fait réellement runOnUiThread?

  • Android runOnUiThread met en file d'attente un Runnable à exécuter sur le thread d'interface utilisateur. Ceci est important car vous ne devez jamais mettre à jour l'interface utilisateur à partir de plusieurs threads. runOnUiThread utilise un Handler.

    Sachez que si la file d'attente du thread d'interface utilisateur est pleine ou si les éléments à exécuter sont longs, il peut s'écouler un certain temps avant que votre Runnable en file d'attente ne s'exécute réellement.

Qu'est-ce qu'un gestionnaire?

  • Un gestionnaire vous permet de publier des runnables à exécuter sur un thread spécifique. Dans les coulisses, runOnUi Thread met en file d'attente votre Runnable avec le gestionnaire d'interface utilisateur d'Android afin que votre exécutable puisse s'exécuter en toute sécurité sur le thread d'interface utilisateur.
23
William Morrison

1. Pourquoi exécutable?

Runnable est juste une interface dont vous avez besoin pour instancier un thread pour le contenir. Alors que thread contient déjà la possibilité de générer un thread.Si vous étendez Thread, vous ne pouvez pas étendre autre chose (Java ne prend pas en charge l'héritage multiple). Vous pouvez avoir plusieurs interfaces sur une classe, donc vous pouvez avoir Runnable.

De plus, lorsque vous étendez la classe Thread, chacun de vos threads crée un objet unique et s'associe à lui. Lorsque vous implémentez Runnable, il partage le même objet sur plusieurs threads.

2. Pourquoi utiliser le gestionnaire et qu'est-ce que c'est?

Le gestionnaire est écrit en Java (utiliser en interne un thread), donc tout ce que vous pouvez faire avec le gestionnaire, vous pouvez également utiliser un thread.

Alors pourquoi utiliser Handler? La raison est comme ci-dessous

  • Le gestionnaire vous permet d'envoyer et de traiter des objets Message et Runnable associés à MessageQueue d'un thread. Pour le dire en termes simples, le gestionnaire facilite votre travail.

  • Android a deux règles principales pour gérer les threads:

  • Ne bloquez pas le thread d'interface utilisateur

  • N'accédez pas au Android UI toolkit from outside the UI thread

Pour lier les 2 règles énoncées ci-dessus, dans Android nous avons 3 méthodes intégrées qui peuvent gérer la situation lorsque l'une de vos classes d'activité est exécutée ou appelée à partir d'un thread différent.

Nous pouvons ensuite planifier les mises à jour de l'interface utilisateur à exécuter sur le thread d'interface utilisateur avec ces trois méthodes ci-dessous. L'activité ou la vue fonctionne alors comme un gestionnaire (plus d'informations sur les gestionnaires ci-dessous) et planifie votre exécutable sur le thread d'interface utilisateur:

  1. Activity.runOnUiThread (exécutable)
    1. View.post (exécutable)
    2. View.postDelayed (Runnable, long) // (long = temps de planification)

. Qu'est-ce que le fil d'interface utilisateur?

Le thread d'interface utilisateur est le thread principal dans lequel les éléments d'interface utilisateur tels que la vue et l'activité sont rendus. Aucune opération consommatrice de temps ne doit se produire dans le thread d'interface utilisateur. La valeur par défaut de l'application s'exécute dans le thread d'interface utilisateur. Vous n'avez rien à faire de spécial pour utiliser le thread d'interface utilisateur.

10
Prem

Handler, Runnable et Threads fonctionnent ensemble, je ne pense pas que vous devriez les comparer.

Gestionnaire

permet d'envoyer des messages entre deux threads de manière sûre, ce qui signifie que l'envoi de thread place le message dans la file d'attente des threads de destination, et cette file d'attente de destination traitera ce message au moment approprié.

Runnable

c'est une interface que vous implémentez, dans l'implémentation vous mettez la logique que vous voulez exécuter sur un thread. Vous pouvez réellement utiliser Runnable également dans des endroits non liés au thread. Beaucoup de Java apis utilisent réellement Runnable, pas seulement les threads. Vous pouvez publier Runnable en utilisant le gestionnaire, ou vous pouvez l'utiliser avec des exécuteurs. Les Runnables sont sympas parce que vous pouvez les implémenter sous une forme d'implémentation anonyme .

UniThread

tu voulais dire UI Thread? La plupart des interfaces utilisateur implémentent son fonctionnement dans un seul thread, tous les éléments de l'interface utilisateur: les fenêtres/widgets communiquent à l'aide de messages (tout comme dans le gestionnaire). C'est à dire. l'utilisateur appuie sur le bouton, cela lance un message avec des informations sur le bouton, il est envoyé au thread d'interface utilisateur et finalement remis à votre auditeur.

Dans Android il est interdit (entraîne une exception) de modifier les éléments d'interface utilisateur à partir d'un thread non UI, cela a du sens - si vous le modifiez à partir d'un autre thread, cela pourrait se produire pendant que le thread d'interface utilisateur effectue des changements au même widget - résultant en un comportement indéfini.

4
marcinj

J'utilise Threads pour l'exécuter. Habituellement, j'écrivais une classe qui étend Thread et implémentait la méthode run.

Quel est l'intérêt de Runnable si l'on peut écrire le code d'arrière-plan dans la méthode d'exécution de Thread?

L'utilisation de Runnable et la création d'un thread à partir de Runnable est une pratique générale.

Depuis le didacticiel Oracle sur accès simultané concernant Runnable Vs Thread utilisation:

L'objet Runnable est plus général, car l'objet Runnable peut sous-classer une classe autre que Thread.

2.Comment le gestionnaire est-il utilisé à l'intérieur du fil et pourquoi devons-nous l'utiliser.

C'est un vaste sujet à expliquer. En termes plus simples à partir du site de documentation officiel:

  1. Handler vous permet d'envoyer et de traiter les objets Message et Runnable associés au MessageQueue d'un thread. Chaque instance de Handler est associée à un seul thread et à la file d'attente de messages de ce thread.

  2. Lorsque vous créez un nouveau Handler, il est lié à la file d'attente de threads/messages du thread qui le crée - à partir de ce moment, il fournira des messages et des exécutables à cette file d'attente de messages et les exécuter lorsqu'ils sortent de la file d'attente de messages.

  3. Il existe deux utilisations principales d'un Handler: (1) pour planifier des messages et des runnables à exécuter à un moment donné dans le futur; et (2) pour mettre en file d'attente une action à effectuer sur un thread différent du vôtre

  4. Lorsqu'un processus est créé pour votre application, son thread principal est dédié à l'exécution d'une file d'attente de messages qui gère la gestion des objets d'application de niveau supérieur (activités, récepteurs de diffusion, etc.) et toutes les fenêtres qu'ils créent. Vous pouvez créer vos propres threads et communiquer avec le thread d'application principal via un gestionnaire. Cela se fait par appeler la même publication ou les méthodes sendMessage qu'avant, mais à partir de votre nouveau thread. Le Runnable ou le message donné sera alors planifié dans la file d'attente de messages du gestionnaire et traité le cas échéant.

Cette image de blog.mindorks.com article par Anishar ALi explique clairement les concepts.

enter image description here

3.Android a une autre chose appelée runOnUiThread, comment utilisons-nous cela? Je sais qu'il est utilisé pour mettre à jour l'interface utilisateur.

Vous pouvez trouver plus de détails en examinant l'implémentation de runOnUiThread

/**
     * Runs the specified action on the UI thread. If the current thread is the UI
     * thread, then the action is executed immediately. If the current thread is
     * not the UI thread, the action is posted to the event queue of the UI thread.
     *
     * @param action the action to run on the UI thread
     */
    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

Reportez-vous à l'article ci-dessous pour un exemple de code d'utilisation de Handler.

Android: Toast dans un fil

1
Ravindra babu

Quel est l'intérêt de Runnable si l'on peut écrire le code d'arrière-plan dans la méthode d'exécution du thread?

Runnable est une interface utilisée pour créer une nouvelle classe de threads similaire à la classe de thread créée en étendant Java.lang.Thread classe. La seule différence est que l'interface Runnable permet à la classe d'étendre une autre classe (si nécessaire) pour remplacer/hériter des fonctionnalités d'une classe. Extension Java.lang.Thread la classe révoquera cette capacité.

De plus, l'interface exécutable représente une tâche qui peut être exécutée par un thread simple ou des exécuteurs ou tout autre moyen. la séparation logique de Task comme Runnable que Thread est une bonne décision de conception.

En savoir plus: http://javarevisited.blogspot.com/2012/01/difference-thread-vs-runnable-interface.html#ixzz2qgjDYJhT

0
Ankur Shanbhag

L'interface Runnable est le parent de la classe Thread et run () est la méthode de l'interface Runnable Donc, normalement, nous devrions préférer l'interface Runnable à l'extension de la classe thread car nous ne voulons pas changer le comportement de la classe et nous pouvons également étendre une autre classe. en réalisant un couplage lâche ainsi que nous avons l'avantage de changer l'interface utilisateur de toute autre classe.

Nous pouvons changer l'interface utilisateur de 4 façons

1.En utilisant l'exemple du gestionnaire

public class MainActivity extends AppCompatActivity {    
private Handler mainHandler=new Handler();
class ExampleRunnable implements Runnable {
        int seconds;

        public ExampleRunnable(int seconds) {
            this.seconds = seconds;
        }

        @Override
        public void run() {
            for (int i = 0; i < seconds; i++) {
 mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                        button.setText("50% process completed");
                        }
                    });

2.En utilisant runOnUIThread (), nous devons attacher runOnUIThread avec un message, cela peut être facilement compris avec l'exemple

class ExampleRunnable implements Runnable {
        int seconds;



 public ExampleRunnable(int seconds) {
        this.seconds = seconds;
    }

    @Override
    public void run() {runOnUIThread.post(new Runnable() {
                    @Override
                    public void run() {
                        button.setText(" Runnable");
                    }
                });
            }

3.En utilisant n'importe quelle vue, nous pouvons appeler par n'importe quelle vue ici, j'ai appelé avec interrupteur

public class MainActivity extends AppCompatActivity {
 private Switch aSwitch;
@Override
    protected void onCreate(Bundle savedInstanceState) {
 aSwitch=findViewById(R.id.switch1);
class ExampleRunnable implements Runnable {
            int seconds;



     public ExampleRunnable(int seconds) {
            this.seconds = seconds;
        }

        @Override
        public void run() { aSwitch.post(new Runnable() {
                        @Override
                        public void run() {
                            button.setText(" Runnable");
                        }
                    });
                }

En créant Handler dans un autre thread, nous devons définir Looper car par défaut, il nous attache à notre thread looper

Handler threadHandler=new Handler(Looper.getMainLooper());
threadHandler.post(new Runnable()
{
                            @Override
                            public void run() {
                                button.setText(" Runnable");
                            }
                        });
                    }

Il y a 4 façons de l'implémenter, donc je pense que vous pouvez maintenant quelque chose sur le thread exécutable et runOnUIThread () et le gestionnaire est magnifiquement écrit par une autre personne.

0
Harshit Joshi