我很困惑(java新手):
实现Runnable接口时,必须重写run()方法才能获得线程执行功能。实现此接口使您的对象成为Runnable(?)类型。如何通过简单地实现Runnable接口来“注入”线程功能?基本上,当您实例化一个实现Runnable的类时,在线程功能中会发生什么?我可能在这里误解了一些基本的OO概念。感谢。
在执行thread.start()时,JVM是否“知道”寻找runnable?
答案 0 :(得分:9)
当您创建Runnable
的实现时,没有任何东西将您的类与JVM的线程容量联系起来。 Runnable
接口的实例就像是任何其他接口的实例,只是另一个实例。
如果要使用JVM的线程系统,则必须使用Thread
类的新实例,该实例将运行run()
实现的Runnable
方法。一个单独的线程。
关于创建新线程的所有逻辑都由Thread
类完成。
答案 1 :(得分:4)
Runnable表示“可以”在一个单独的线程中运行的工作(你可以自己调用Runnable.run())。
但是,要在单独的线程中调用Runnable,请执行类似
的操作Thread thread = new Thread(new MyRunnable());
thread.start(); // MyRunnable will now be invoked in a new thread
答案 2 :(得分:2)
背景中没有什么特别的事情发生。
实施Runnable
界面可确保您的班级拥有public void run()
方法。
将自定义类传递到Thread
时,真正发生了神奇的事。
Thread th = new Thread(new YourCustomRunnable());
th.start();
在上面的代码中,将创建一个新的Thread
,run()
方法中的代码将在另一个线程中运行。
在线程内部,线程将调用您的自定义run()
方法,并使该代码在单独的线程上运行。从技术上讲,可以执行以下操作:
Runnable r = new MyCustomRunnable();
r.run();
在上面的代码中,r
不会在单独的线程上运行。
答案 3 :(得分:2)
实现Runnable不启动新线程,启动创建新Thread对象并启动它所需的新线程,并且Thread最常用的构造函数之一将Runnable作为参数(Thread(Runnable) ):
Thread t = new Thread(new MyRunnable());
t.start();
答案 4 :(得分:2)
实现Runnable并不会让你的类在一个线程上运行。相反,您可以执行以下操作:
Runnable myRunnable = new MyRunnable(); // MyRunnable implements Runnable
Thread t = new Thread(myRunnable);
t.start();
现在,myRunnable的run()方法中的代码将在一个单独的线程中执行。我建议您查看java.util.concurrent包中的ExecutorService和Executors。这些对象将执行您在线程中传入(Runnable)的内容。使用Executor / ExecutorService的优点是,您可以预先定义要分配的线程数,并采用各种策略来增长/缩小或保持常量。
新手感兴趣的另一件事:线程可以是守护进程(后台)或非守护进程(如UI)线程。如果有非守护程序线程在运行,您的JVM将不会死亡。要将Thread声明为守护进程,只需调用setDaemon()即可。使用执行程序,您需要提供一个ThreadFactory,您可以在其中创建线程并将其标记为守护程序。
希望这有帮助。
答案 5 :(得分:1)
界面是一种契约。通过实现Runnable,您承诺将提供界面中定义的所有方法。因此,任何其他类如“Thread”知道Runnable.run()都可以在类的对象上调用此方法。即使不了解你的班级也是如此。
为了使用您的代码启动一个新线程,您需要编写如下内容:
Thread thread = new Thread(new MyRunnable());
thread.start();
start()方法将执行一些操作系统魔术以生成线程,然后在作为参数提供给构造函数的对象上的操作系统线程的上下文中调用run()方法。
答案 6 :(得分:1)
就最近的定义(spring / DI)而言,没有“注入”。 Runnable与任何其他界面没有什么不同。它是一个“契约”,表明你的类提供了在界面中调出的任何必要的方法。