【问题标题】:Best way of creating and using an anonymous Runnable class创建和使用匿名 Runnable 类的最佳方式
【发布时间】:2012-09-28 02:24:18
【问题描述】:

我想为Runnable 使用匿名类。有两种方法,但我不知道他们是否做同样的事情:

方法一:直接使用Runnable,然后调用run()

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

方法二:创建匿名Runnable并粘贴到Thread,使用start()方法代替run()

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

我认为方法二显然是正确的。但是,我不知道它是否与方法一做同样的事情。我们可以直接在Runnable 上调用run() 方法吗?

【问题讨论】:

    标签: java multithreading runnable


    【解决方案1】:

    不,您通常不会直接在 Runnable 上调用 run(),因为这样您不会获得后台线程。如果您不想要并且需要后台线程,则可以直接调用run(),否则如果您想创建后台线程并从其中运行 Runnable,则必须创建一个新线程,然后传入 Runnable进入其构造函数,并调用start()

    此外,还有其他方法可以完成此任务,包括使用 Executors 和 ExecutorServices,您应该研究一下它的用途,因为它们比使用简单的 Thread 对象提供更多的灵活性和功能。

    您还想看看Future 接口和FutureTasks 类的使用,它们与Runnables 类似,只是它们允许您在完成时返回结果。如果您使用过 SwingWorker,那么您已经在不知不觉中使用了 Future 接口。

    【讨论】:

      【解决方案2】:

      正如其他人所提到的,使用 Thread 类是正确的方法。但是,您还应该考虑使用 Javas Executors 框架来处理正在运行的线程。

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

      当然,直接使用 Thread 就可以了。但通常建议(或首选)使用该框架。让 Java 为您处理细节。

      【讨论】:

      • 在这种情况下,有没有办法可以将参数传递给 run() 方法?
      • @kenshinji 不,没有,您必须在实现 Runnable 的类的构造函数中传递这些参数。
      【解决方案3】:

      Runnable 接口必须在Thread 内执行。如果您想找到另一种内联包装的方法,即Thread 中的一段代码,请尝试:

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

      【讨论】:

        【解决方案4】:

        我想在这个讨论中添加一些东西(你已经得到了很好的答案)。
        如果您的 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 虚拟机在内部调用该线程的 run 方法。所以要启动一个线程,我们需要使用接口 Runnable referencence 调用 start 方法。 在方法一中,即使我们不能调用带有 Runnable 接口引用的 start 方法,因为 Runnable 接口不支持 start() 方法。因此必须创建 Thread 类的对象来启动线程执行。

          【讨论】:

            【解决方案6】:

            永远记住,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();
            

            调用 Thread 类的 start() 方法后,run() 方法内部的代码在新创建的线程上运行。

            您还可以查看创建 Runnable 对象的不同方式 here

            【讨论】:

              【解决方案7】:

              这可以通过 lambda 表达式来完成:

              Runnable myRunnable = () -> {
                  //code you want to execute
              };
              

              【讨论】:

              • 不错。从 Java 8 及更高版本开始支持此功能。
              【解决方案8】:

              第一种方法是错误的:它没有创建新线程,所以没用。

              这就像将代码放在可运行文件之外。

              请注意,有两种方法可以在匿名类 as described in Thread's javadoc 中定义的代码上启动新线程,但您的 方法 1 不在其中,您的方法 2 是您通常应该首选的方法。

              【讨论】:

                【解决方案9】:

                正如@Hovercraft 所述,如果您直接调用Runnable.run() 方法,则根本不会创建Thread。就像调用任何其他方法一样(System.out.println(...),...)。

                当您将Runnable 对象传递给Thread 构造函数时,会将Thread 中的target 字段设置为您的对象:

                this.target = target;
                

                然后,当您在Thread 上调用start() 时,这会分叉新线程并调用Thread.run() 方法。 Thread.run()依次调用目标的run()方法:

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

                因此,将Runnable 传递给Thread,然后调用start() 是在后台单独线程中运行Runnable 的方法。

                【讨论】:

                  【解决方案10】:

                  你的方法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();
                      } 
                  }
                  

                  【讨论】:

                    【解决方案11】:

                    这是一个简单的代码示例,说明如何正确创建匿名 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
                                    }
                                }
                            }
                        }
                    
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2013-05-17
                      • 2020-11-22
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-06-29
                      • 2011-03-11
                      • 1970-01-01
                      相关资源
                      最近更新 更多