我想为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
方法吗?
谢谢:)
答案 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
}
}
}
}
}