在java中,每个线程的创建和控制都是由java.lang.Thread类的独特对象实现的。一个独立的应用运行时,会自动创建一个用户线程,执行main()方法。这个线程叫做主线程。
在java中,实现线程有以下两种方式:
- 通过实现java.lang.Runnable接口;
- 通过扩展java.lang.Thread类。
实现Runnable接口:
public interface Runnable{
void run();
}
要用这个接口创建和使用线程,步骤如下:
(1)创建一个实现Runnable接口的类,该类对象是一个Runnable对象。
(2)创建一个Thread类型的对象,并将Runnable对象作为参数传入Thread构造函数。于是,这个Thread对象包含一个实现run()方法的Runnable对象。
(3)调用上一步创建的Thread对象的start()方法。
public class RunnableThreadExample implements Runnable{
public int count=0;
public void run() {
System.out.println("RunnableThread starting.");
try{
while (count<5){
Thread.sleep(500);
count++;
}
}catch(InterruptedException exc){
System.out.println("RunnableThread interrupted.");
}
System.out.println("RunnableThread terminating");
}
}
public static void main(String[] args){
RunnableThreadExample instance = new RunnableThreadExample();
Thread thread = new Thread(instance);
thread.start();
/*等到上面的线程数到5*/
while(instance.count !=5){
Thread.sleep(250);
}catch(InterruotedException exc){
exc.printStackTrace();
}
}
从上面的代码可以看出,我们真正需要做的就是让类实现run方法。然后另一个方法就是将这个类的实例传入new Thread(obj),并调用那个线程的start()。
扩展Thread类:
创建线程还有一种方式,就是通过扩展Thread类实现。使用这种方法就意味着要重写run()方法,并且在子类的构造函数里,还需要显式调用这个线程的构造函数。
public class ThreadExample extends Thread {
int count = 0;
public void run(){
System.out.println("Thread starting");
try{
while (count<5){
Thread.sleep(500);
System.out.println("In Thread,count is" + count);
count++;
}
}catch(InterruptedException exc){
System.out.println("Thread interrupted.");
}
System.out.println("Thread terminating.");
}
}
public class ExampleB{
public static void main(String args[]){
ThreadExample instance = new ThreadExample();
instance.start();
while(instance.count !=5){
try{
Thread.sleep(250);
}catch(InterruptedException exc){
exc.printStackTrace();
}
}
}
}
这段代码跟之前的做法非常相似。两者的区别在于,既然是扩展Thread类而非只是实现一个接口,因此可以在这个类的实例中调用start()。
- 在创建线程时,相比扩展Thread类,实现Runnable接口可能更优。
Java不支持多重继承。因此,扩展Thread类也就意味着这个子类不能扩展其他类,而实现Runnable接口的类还能扩展其他一个类。 - 类可能只要求可执行即可,因此扩展整个Thread类代价过大
。