创建和使用匿名 Runnable 类的最佳方式
Posted
技术标签:
【中文标题】创建和使用匿名 Runnable 类的最佳方式【英文标题】:Best way of creating and using an anonymous Runnable class 【发布时间】: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()
方法吗?
【问题讨论】:
【参考方案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
【讨论】:
以上是关于创建和使用匿名 Runnable 类的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章