Maison  >  Questions et réponses  >  le corps du texte

Pourquoi passer un objet de sous-classe de l'interface Runnable au constructeur de Thread ?

De plus, par rapport au thread, outre l'héritage, comment l'indépendance du code et des données se reflète-t-elle dans runnable ? Comme écrit sur certains blogs, le thread ne peut pas partager de ressources, mais runnable peut partager des ressources. N'est-il pas suffisant de changer les variables du thread en statiques ? Tout comme ce que dit l'article suivant http://blog.csdn.net/uudou/ar...

巴扎黑巴扎黑2661 Il y a quelques jours1519

répondre à tous(3)je répondrai

  • 漂亮男人

    漂亮男人2017-06-12 09:21:22

    Cela ne semble pas avoir grand-chose à voir avec les données. Je pense que Runnable présente deux avantages :

    1. Après avoir implémenté Runnable, vous pouvez ouvrir un fil de discussion à exécuter (généralement en utilisant executorService.exec(command),挫一点也可以用new Thread(command).start()),也可以不开线程阻塞式的跑(直接调用command.run()) ;

    2. Java 1.8 et versions ultérieures peuvent être exécutées avec Lambda, par exemple :
    3. new Thread(() -> {
          // Do something
      }).start();
      
      
      

      répondre
      0
  • 代言

    代言2017-06-12 09:21:22

    Runnable的好处是各种场景都可以用,比如你可以让任何一个Class implements Runnable,但是extends ThreadIl existe certaines limitations. En raison de l'héritage unique Java, il ne peut pas être utilisé dans certains scénarios.

    répondre
    0
  • 天蓬老师

    天蓬老师2017-06-12 09:21:22

    Réponse :

    Ce problème est considéré comme un problème de conception.

    La raison pour laquelle Thread et Runnable sont séparés est de séparer complètement le « processus de création » du thread de la « logique d'exécution » du thread.

    C'est-à-dire :
    Le processus de création d'un thread est du « code »
    La logique d'exécution d'un thread est des « données » ;

    Cela semble un peu déroutant, n'est-ce pas tout du code JAVA ? Pourquoi le code redevient-il des données ?

    Nous ne sommes pas empêtrés dans ces concepts. Je pense que nous pouvons réfléchir à cette question à l'envers et donner un exemple pour illustrer le problème.

    Processus de discussion :

    Par exemple, je souhaite concevoir un programme monothread. Ce monothread doit accomplir deux tâches :

    1. Imprimez une phrase bonjour tout le monde ;

    2 Calculez la somme des deux nombres int a et int b et affichez-la ;
    Remarque : Qu'est-ce que l'exécution 1 ? Ou 2 ? Il est déterminé par le paramètre n, n est un nombre aléatoire...

    Afin d'exécuter ces deux tâches dans le même thread, nous pouvons écrire du code comme celui-ci :

    float n = (float)Math.random();
    
    int a = 1;
    int b = 1;
    
    Thread t = new Thread() {
        @Override
        public void start() {
            if (n >= 0.5f) {
                System.out.println("hello world");
            } else {
                System.out.println(a + b);
            }
        }
    };
    
    t.start();
    

    Le code ci-dessus peut en effet terminer la tâche, mais le problème est qu'on confond le "processus de création" et la "logique métier" du thread...

    Ce n'est pas bon. D’ailleurs, au niveau du système d’exploitation, le processus de création de thread est en fait très compliqué !

    Le langage Java encapsule cette complexité à l'abri des regards. Bien que le code ne soit qu'une classe Thread et qu'il ne semble y avoir aucun seuil pour l'appeler, le processus de création de Thread est toujours très compliqué et consomme des ressources.

    Retour aux affaires, maintenant j'ajoute à nouveau une petite exigence En plus des 1 et 2 précédents, j'ajoute également un 3 pour afficher l'horodatage actuel du système.

    La tâche devient donc :

    1. Imprimer une phrase hello world ;

    2. Calculer la somme des deux nombres int a et int b et afficher l'horodatage actuel du système ;
    Notez qu'à ce stade, nous devons modifier le processus de création du Thread, c'est-à-dire modifier la fonction de démarrage :

    float n = (float)Math.random();
    
    int a = 1;
    int b = 1;
    
    Thread t = new Thread() {
        @Override
        public void start() {
            if (n >= 0.33f) {
                System.out.println("hello world");
            } else if (n >= 0.66f) {
                System.out.println(a + b);
            } else {
                System.out.println(System.currentTimeMillis()); // 这里是新增的语句
            }
        }
    };
    
    t.start();
    

    Cette discussion se termine, observons attentivement... En fait :

    Thread t = new Thread() {
        @Override
        public void start() {
            // ...
        }
    }
    

    Cette partie du code reste inchangée, seul le code de la fonction start est modifié au fur et à mesure de l'évolution des besoins.

    Alors pouvons-nous regrouper cette partie du contenu modifié dans une interface ? ?

    Cela devrait être une bonne idée !

    Thread t = new Thread() {
        private Runnable runnable; // 这里定义一个 Runnable 类型的成员
    
        @Override
        public void start() {
            if (null != this.runnable) {
                runnable.run(); // 在这里用接口来把频繁变化的业务逻辑从线程代码里给拿出去,只调用 run 函数
            }
        }
    }
    

    Je ne sais pas si vous l’avez bien compris maintenant ? :D

    Haha, la classe Thread de Java ne fournit-elle pas simplement un constructeur avec des paramètres Runnable ?

    Nous mettons le code métier dans la classe d'implémentation de l'interface Runnable :

    class BizLogicRun implements Runnable {
        @Override
        public void run() {
            float n = (float)Math.rand();
    
            int a = 1;
            int b = 1;
    
            if (n >= 0.33f) {
                System.out.println("hello world");
            } else if (n >= 0.66f) {
                System.out.println(a + b);
            } else {
                System.out.println(System.currentTimeMillis()); // 这里是新增的语句
            }
        }
    }
    

    Donc finalement, on peut l'appeler ainsi :

    Thread t = new Thread(new BizLogicRun());
    t.start();
    

    Cela complète la séparation complète du « processus de création » et de la « logique métier » du fil ! Cette « scission » a également ouvert la voie à la technologie Java Thread Pool.

    Pour être honnête, Thread t = new Thread() { ... } dans l'exemple de code est assez simple, mais créer un Thread dans le pool de threads n'est pas si simple.

    Donc le « split » est très nécessaire !

    Aussi, pouvons-nous imaginer :

    class PoolRun implements Runnable {
        List<Runnable> runnableList;
    }
    

    Que se passe-t-il si la classe d'implémentation Runable contient une liste Runnable ?

    Résumé :

    1. Le but de l'utilisation de l'interface Runnable est de séparer complètement le « processus de création » du thread de la « logique d'exécution » du thread ;
    2. Thread ne peut pas partager de ressources, mais Runnable peut partager des ressources. ;
    3. Au cours de la discussion, nous sommes passés du concret à l'abstrait
    4 Le code que j'ai donné dans l'exemple est en effet relativement simple, mais j'espère qu'il pourra expliquer clairement le problème ;

    D'accord, ce qui précède est ma réponse à cette question, j'espère que cela vous sera utile.

    répondre
    0
  • Annulerrépondre