Подтвердить что ты не робот

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

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

Метод первый: непосредственное использование Runnable и последующий вызов run():

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

Способ второй: создайте анонимный Runnable и вставьте его в Thread, используя метод start() вместо run():

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

Я хотел бы добавить что-то в эту дискуссию (у вас уже есть хорошие ответы).
Если ваш объект 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

Ответ 5

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

Ответ 6

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

Это похоже на то, как поставить код за пределы исполняемого файла.

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

Ответ 7

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

Когда вы передаете объект Runnable конструктору Thread, который устанавливает в поле Thread поле target в качестве объекта:

this.target = target;

Затем, когда вы вызываете start() на Thread, это выполняет работу по разветвлению нового потока и вызову метода Thread.run(). Thread.run() вызывает целевой метод run() по очереди:

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

Итак, передаем Runnable в Thread, а затем вызов start() - это способ запустить ваш Runnable в фоновом режиме в отдельном потоке.

Ответ 8

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

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

Ответ 9

Ваш метод 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();
    } 
}

Ответ 10

Вот простой пример кода того, как правильно создать анонимный класс 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
                }
            }
        }
    }

}