Лучший способ создания и использования анонимного класса Runnable

Я хочу использовать анонимный класс для Runnable. Есть два способа, но я не знаю, делают ли они то же самое или нет :

метод один: использование непосредственно Runnable и вызов run

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

Метод второй: создайте анонимный runnable и вставьте в поток, используя метод start вместо run:

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

Я думаю, что метод два очевиден. Но я не знаю, делает ли он то же самое, что и метод один ? Мы можем позвонить run метод на Runnable сразу ?

спасибо :)

10 ответов


нет, вы обычно не называют run() непосредственно на Runnable, поскольку вы не получите фоновой резьбы таким образом. Если вы не хотите и вам нужен фоновый поток, то fine call run() напрямую, но в противном случае, если вы хотите создать фоновый поток и запустить свой Runnable из него, вы должны создать новый поток, а затем передать Runnable в его конструктор и вызвать start().

кроме того, есть другие способы выполнения этой задачи, включая использование исполнителей и ExecutorServices, и вы должны изучить использование этого, поскольку они предлагают больше гибкости и мощности, чем использование объекта потока голых костей.

также вы захотите взглянуть на использование будущее интерфейс и FutureTasks класс, который похож на Runnables, только они позволяют возвращать результат по завершении. Если вы использовали SwingWorker, то вы уже использовали будущий интерфейс, не осознавая этого.


Как уже упоминалось, использование класса Thread является правильным способом. Тем не менее, вы также должны заглянуть в использование Javas исполнители framework для обработки запущенных потоков.

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

конечно, просто использовать поток напрямую нормально. Но обычно рекомендуется (или предпочтительно) использовать фреймворк. Пусть Java обрабатывает мелкие детали для вас.


ваш метод 1 не делает sens. The Runnable интерфейс имеет значение для потоковой передачи только при выполнении внутри Thread (Способ 2). Если вы хотите найти другой способ обернуть встроенный фрагмент кода внутри потока, это может быть один:

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

Я хотел бы добавить что-то в этом обсуждении (у вас уже есть хорошие ответы).
Если ваш объект Runnable не имеет состояния, чтобы уменьшить выделение памяти (что занимает время + потребляет некоторую память - подумайте о случае, когда приложение широко использует потоки), пожалуйста, рассмотрите статическое поле, содержащее объект 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

в методе one он будет работать как метод, как Runnable интерфейс, реализующий и вызывающий его, но не будет создан фоновый поток. Дело в том, что когда мы вызываем метод start, он заставляет поток corrosponding начать выполнение, виртуальная машина Java вызывает метод run этого потока внутренне . Поэтому для запуска потока нам нужно вызвать метод start с интерфейсом Runnable refernce . В методе один даже мы не можем вызвать метод start с ссылкой на интерфейс Runnable как Runnable интерфейс не поддерживает метод start ().Поэтому его обязательным для создания объекта класса Thread для запуска выполнения потока .


первый способ неправильный: он не создает новый поток, поэтому он бесполезен.

Это так же, как положить код вне runnable.

отметим, что есть два способа запуска нового потока в коде, определенном в анонимном классе,как описано в javadoc потока но ваш Способ 1 нет среди них и ваших Способ 2 - это тот, который вы обычно предпочитаете.


как @воздушной подушке mentionds, если вы называете Runnable.run() метод напрямую, a Thread не создается вообще. Это так же, как вызов любого другого метода (System.out.println(...), ...).

при передаче Runnable объект Thread конструктор, который задает


всегда помните, что Runnable-это просто код, который вы хотите или может работать в потоке. Один из способов анонимно определить запускаемый код:

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

и затем вы можете создать поток и передать созданный Вами Runnable в этот Новый Поток, как это

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

после вызова метода start() класса Thread код, который входит в метод run (), запускается во вновь созданном потоке.

вы также можете посмотреть другой способ создания работоспособных объект здесь


ваш метод 1 обычно не может выполнять никакой полезной работы. С помощью этого метода, если вы хотите получить вывод простого HelloWorld.java-программа т. е. "Hello World", она будет напоминать следующий бесполезный код, но она печатает"Hello World". Поэтому вы должны использовать свой второй метод. Бесполезный код:

class MyRunnable implements Runnable {

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

    public static void main(String[]arg){ 
    MyRunnable myRunnable = new NamedRunnable( );
    namedRunnable.run();
    } 
}

вот простой пример кода, Как правильно создать анонимный класс Runnable и обработать утечку памяти (пример для 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
                }
            }
        }
    }

}