从我在Java中使用线程的时间来看,我发现了两种编写线程的方法:
使用可运行的机具:
public class MyRunnable implements Runnable {
public void run() {
//Code
}
}
//Started with a "new Thread(new MyRunnable()).start()" call
或者,使用扩展线程:
public class MyThread extends Thread {
public MyThread() {
super("MyThread");
}
public void run() {
//Code
}
}
//Started with a "new MyThread().start()" call
这两个代码块有什么显著的区别吗?
线程保持不打算访问的行为;
它的同步锁用于连接等。它有一些你可以偶然访问的方法。
但是,如果您的子类Thread必须考虑实现更多Thread。
public class ThreadMain {
public int getId() {
return 12345678;
}
public String getName() {
return "Hello World";
}
public String getState() {
return "testing";
}
public void example() {
new Thread() {
@Override
public void run() {
System.out.println("id: "+getId()+", name: "+getName()+", state: "+getState());
}
}.start();
}
public static void main(String[] args) {
new ThreadMain().example();
}
}
如果你运行这个,你可能会期望
id: 12345678, name: Hello World, state: testing
然而,您并没有调用您认为是的方法,因为您使用的是Thread而不是ThreadMain中的方法,相反,您会看到类似
id: 11, name: Thread-0, state: RUNNABLE
1.扩展线程接口,就像让类只作为线程一样。您的新类将像一个增强的线程。
jshell> public class Test extends Thread{
...> public Test(String name){
...> super(name);
...> }
...> public void run(){
...> System.out.println(Thread.currentThread().getName());
...> }
...> }
| created class Test
jshell> Test t1=new Test("MyThread");
t1 ==> Thread[MyThread,5,main]
它创建一个线程,而不是Test对象。所以它会像一个线程。不能在线程之间共享Test类的实例。
2.实现可运行接口。
jshell> public class Test1 implements Runnable{
...> public void run(){
...> System.out.println(Thread.currentThread().getName());
...> }
...> public String getName(){
...> return "testing";}
...> }
| created class Test1
jshell> Test1 t1=new Test1();
t1 ==> Test1@396a51ab --> this creates Test1 object.
该对象可以通过以下方式跨线程共享,
jshell> Thread t1=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]
jshell> Thread t=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]
我认为已经有很多关于这个话题的讨论,认为这可能对基础知识有所帮助。
如果我没有错的话,它或多或少类似于
接口和抽象类之间的区别是什么?
extends建立“Is A”关系,接口提供“Has A”功能。
首选工具可运行:
如果不需要扩展Thread类并修改Thread API默认实现如果你执行的是一个火灾和忘记命令如果您已经在扩展另一个类
首选“扩展线程”:
如果必须重写oracle文档页中列出的任何线程方法
通常,您不需要重写线程行为。因此,在大多数情况下,首选实现Runnable。
另一方面,使用高级ExecutorService或ThreadPoolExecutorServiceAPI提供了更多的灵活性和控制。
看看这个SE问题:
ExecutorService vs休闲线程生成器