一、用Runnable是实现线程
先继承Runnable 实现run方法再使用new Thread(该类)实现
/**
* 用Runnable 方式创建线程
* @author cyd
*
*/
public class RunnableStyle implements Runnable{
public static void main(String []args) {
Thread thread=new Thread(new RunnableStyle());
thread.start();
}
public void run() {
System.out.println("用Runnable方法实现线程");
}
}
二、用Thread方式实现进程
先用类继承Thread,重写父类run方法,再通过实例化该类实现
/**
* 用Thread方式实现线程
* @author cyd
*
*/
public class ThreadStyle extends Thread{
public static void main(String[] args) {
// TODO Auto-generated method stub
new ThreadStyle().start();
}
public void run() {
System.out.println("用Thread类实现线程");
}
}
通常方法一更好。方法二一般不建议使用,方法二缺点如下:
- 1:应该和Thread解耦
- 2:每次新建任务要新建独立线程,如果用Runnable就可以用线程池,节约资源
- 3:因为继承了Thread不能继承其他类了,减少了扩展性
两种方法的区别:
方法一中的run方法
/* What will be run. */
private Runnable target;
@Override
public void run() {
if (target != null) {
target.run();
}
}
可以看见很简单,传过来的target是Runnable对象,不为空就执行target.run()方法
而方法二的run方法是重写,把该段给覆盖了,不执行这段判断的代码了
以上就是两种方法的本质区别
思考:如果同时使用两种方法会怎么样?
这部分代码有点复杂,先用第一种方式利用匿名内部类实例一个Thread(Runnable对象),实现该匿名内部类的run方法,然后重写这个Thread对象的run方法。最后Thread对象star()```
/**
* 同时使用两种实现线程的方法
* @author cyd
*
*/
public class BothRunnableThread {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("我来自Runnable");
}
}) {
@Override
public void run() {
System.out.println("我来自Thread");
}
}.start();
}
}
运行结果:
public class BothRunnableThread1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread B=new Thread(new A()) {
public void run() {
System.out.println("我是Thread");
}
};
B.start();
}
}
class A implements Runnable {
public void run() {
System.out.println("我是Runnable");
}
}
换了代码的一种方式会发现容易懂好多,会发现其实运行了B的重写的Run方法
总结:准确的说创建线程只有一种方式那就是构造Thread类,而实现线程的执行单元有两种方式
- 方法一:实现Runnable接口的run方法,并把Runnable实列传给Thread类
- 方法二:重写Thread的run方法(继承Thread类)