42

我想为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吗?

4

11 回答 11

27

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

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

此外,您还需要了解Future接口和FutureTasks类的使用,它们与 Runnables 类似,只是它们允许您在完成时返回结果。如果您使用过 SwingWorker,那么您已经使用过 Future 接口而没有意识到它。

于 2012-10-07T18:22:35.933 回答
27

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

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

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

于 2012-10-07T18:38:05.643 回答
6

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

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

t.start();
于 2012-10-07T18:29:47.847 回答
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
于 2012-10-07T19:42:12.727 回答
2

在方法一中,它就像实现和调用它的 Runnable 接口的方法一样工作,但不会创建后台线程。事实上,当我们调用 start 方法时,它会导致相应的线程开始执行,Java 虚拟机在内部调用该线程的 run 方法。所以要启动一个线程,我们需要使用接口 Runnable referencence 调用 start 方法。在方法一中,即使我们不能调用带有 Runnable 接口引用的 start 方法,因为 Runnable 接口不支持 start() 方法。因此必须创建 Thread 类的对象来启动线程执行。

于 2017-06-14T18:33:43.330 回答
2

永远记住,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 对象的不同方式

于 2017-10-30T14:23:30.797 回答
2

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

Runnable myRunnable = () -> {
    //code you want to execute
};
于 2020-09-28T19:37:44.013 回答
1

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

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

请注意,有两种方法可以在匿名类中定义的代码上启动新线程,如 Thread 的 javadoc 中所述,但您的方法 1不在其中,您的方法 2是您通常应该喜欢的方法。

于 2012-10-07T18:22:40.707 回答
1

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

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

this.target = target;

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

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

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

于 2012-10-07T18:27:18.450 回答
0

你的方法 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();
    } 
}
于 2017-06-24T15:47:23.013 回答
0

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

}
于 2018-01-31T11:44:52.973 回答