创建和使用匿名Runnable类的最佳方法

时间:2012-10-07 18:21:42

标签: java multithreading runnable

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

方法一:直接使用Runnable并调用run

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

方法二:创建一个匿名的runnable,并使用start方法而不是run来粘贴到Thread:

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

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

谢谢:)

11 个答案:

答案 0 :(得分:25)

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

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

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

答案 1 :(得分:24)

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

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

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

答案 2 :(得分:6)

你的方法1不会产生感觉。只有在Runnable(您的方法2)中执行时,Thread接口才对线程有意义。如果你想找到另一种内联包装方式,一个Thread内的一大块代码,可能就是一个:

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

答案 3 :(得分: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

答案 4 :(得分:2)

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

答案 5 :(得分:1)

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

就像把代码放在runnable之外。

请注意在匿名类as described in Thread's javadoc中定义的代码上启动新线程有两种方式,但方法1 不在其中你的方法2 就是你应该喜欢的那个。

答案 6 :(得分:1)

正如@Hovercraft所提到的,如果直接调用Runnable.run()方法,则根本不会创建Thread。这就像调用任何其他方法(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();
    }
}

Runnable传递给Thread,然后调用start(),就可以在后台运行Runnable单独的帖子。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

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

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

答案 9 :(得分: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();
    } 
}

答案 10 :(得分: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
                }
            }
        }
    }

}