我想在一个类下编写多个线程,并找到了一种方法。
public class ThreadExample {
public static void main(String[] arg)
{
Thread one = new Thread() {
public void run() {
try {
Thread.sleep(2000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("One");
}
};
Thread two = new Thread() {
public void run() {
System.out.println("Two");
}
};
one.start();
two.start();
}
}
我没有到达这里,我既没有扩展Thread
类,也没有实现Runnable
接口。我怎么理解这个?
如果答案是“我只是创建Thread
类的对象并使用它,那么为什么不总是这样做而不是做上面提到的事情呢?
答案 0 :(得分:2)
从技术上讲,您正在做的正在扩展Thread
。您正在使用称为匿名内部类的东西进行扩展 - 要了解有关内容的更多信息,请启动here并阅读此页面以及接下来的两页。
这意味着您正在创建没有名称的临时内联子类,并且其定义仅在方法完成后才存在。为什么这样做而不是创建Thread
的命名子类或Runnable
的实现?当run()
的主体与上面的例子一样简单时,它是有意义的 - 键入的内容更少,.java
文件更少,无法跟踪。像这样的一次性简单任务是Thread
的匿名内部类扩展的良好候选者。对于主程序逻辑,您可能希望在单独的文件中执行完整的命名类实现。
此外,一旦您获得了Thread
的良好体验,我建议您查看java.util.concurrent
包。
答案 1 :(得分:2)
啊,但你 匿名延长Thread
班级。
使用new Class() {}
语法时,您创建的anonymous class是指定类的子类(即有效extends
)。
在这种情况下,您已覆盖Thread.run()
方法。
这种方法虽然有效,但它不被认为是“好的设计”,因为你正在扩展Thread,但你并没有创建一种新的Thread。最好将Runnable
传递给构造函数:
new Thread( new Runnable() {
public void run() {
// do something
}
}).start();
答案 2 :(得分:1)
如果你总是像你在问题中那样做,那么你就无法将执行任务的逻辑与任务的运行方式分开。通过实现runnable
,您可以将执行任务的逻辑与管理任务运行方式的代码分开。
如果您使用runnables,您可以在新线程中运行您的任务,在调用线程中运行您的任务,在延迟一段时间后运行您的任务或以其他方式运行它而无需修改runnable中的代码。
使用线程时,通常需要使用ExecutorService而不是直接使用线程类。 Executor服务提供了限制线程数量,处理失败执行,确定runnable何时完成,从其他线程中运行的任务获取返回值等设施。