一道小测试题,一个线程既实现了Runnable接口又继承Thread方法

时间:2022-08-04 17:32:12

今天开学第一天,进行了一次小测验,有道题目是这样的

public class Test extends Thread implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("This is the test"+i);
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread thread = new Thread(new Test());
		thread.start();
	}

}


问程序是否正确执行,会不会报错,大家都知道创建线程有两种方式:

1、继承Thread类,复写其run()方法;(这种方式下,每创建一个子类对象就创建了一个线程

优点是,代码简单,直接编写子类继承Thread类,然后调用new子类对象,直接调用父类的start()方法,start()方法中会调用子类中复写的run()方法,执行自定义的动作。

缺点是,一旦一个类继承了其他的类,就不可以再继承Thread类了。

2、实现Runnable接口,Runnable接口中有一个run()方法,把要执行的代码放到run()方法中。

优点,解决了Java中单继承的局限性,线程实现了Runnable接口,还可以继承其他对象,该方式创建线程时,会传入一个实现了Runnable接口的对象,可以多个线程共享这个实现了Runnable接口的对象,适合多线程处理同一份资源的情况(典型例子就是,多窗口同时卖票)

缺点,较之继承线程的方式创建线程要稍微复杂一些。

实际开发过程中,提倡使用第二种方式创建线程,这种方式比较灵活,更具扩展性。

下面来看下上面的那个程序,Test类既继承了Thread类,又实现了Runnable接口,主函数中

Thread thread = new Thread(new Test());

其实是使用了第二种创建线程的方式,其中传入的对象new Test()是实现了Runnable接口的,这里大家要记住的是Thread类也是实现了Runnable接口的,同样Thread类的子类也是实现了Runnable接口的,所以以上程序改成下面这样也是可以的,

public class Test1 extends Thread {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("This is the test"+this.currentThread().getName()+" "+i);
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		Test1 t1 = new Test1();
//		t1.start();
		Thread thread = new Thread(new Test1());
		thread.start();
	}
}

运行结果截图:

一道小测试题,一个线程既实现了Runnable接口又继承Thread方法

 大家可以看到运行结果:当前线程名为:Thread-1,大家知道线程的默认命名是按照Thread-x(x是从0开始的整数)的规则命名的,那么,Thread-0那个线程呢?

这是因为该类继承了Thread类,当创建一个子类对象时,就会创建一个线程,但是线程要运行的话,一定要调用它的start()方法来开启线程。