您的位置:

Thread和Runnable的区别

一、Thread和Runnable区别

Java中的thread和runnable都是与线程有关的概念,它们之间有什么区别呢?

thread是一个类,可以扩展Java类库,它在实现线程时必须重写run()方法。而runnable是一个接口,它只有一个run()方法需要重写。在实现线程时,通常使用Runnable接口。

//Thread示例
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("Thread");
    }
}

//Runnable示例
class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("Runnable");
    }
}

public class Main {
    public static void main(String[] args){
        //创建Thread对象并启动线程
        MyThread myThread = new MyThread();
        myThread.start();

        //创建Runnable对象并启动线程
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

二、Runnable接口

Runnable接口是一个函数式接口,它只有一个run()方法需要重写,该方法定义了线程要执行的任务的代码逻辑。

实现Runnable接口相对于扩展Thread类更加灵活,因为Java是单继承的,如果扩展了Thread类那么该类就不能再扩展其他的类了,这给程序设计带来了极大的限制。另外,如果需要创建多个线程对象,那么要扩展Thread类需要去创建多个Thread的子类,而实现Runnable接口只需要创建多个Runnable类的实例对象即可。

//Runnable示例
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
            try{
                Thread.sleep(500);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

public class Main {
    public static void main(String[] args){
        //创建Runnable对象并启动线程1
        MyRunnable myRunnable1 = new MyRunnable();
        Thread thread1 = new Thread(myRunnable1, "Thread-1");
        thread1.start();

        //创建Runnable对象并启动线程2
        MyRunnable myRunnable2 = new MyRunnable();
        Thread thread2 = new Thread(myRunnable2, "Thread-2");
        thread2.start();
    }
}

三、Runnable状态

线程状态是指一个线程在某一时刻的状态。Java中的线程有以下六种状态:

  1. New:新建状态,在线程创建后还没有启动时处于此状态
  2. Runnable:就绪状态,当线程调用start()方法后处于此状态
  3. Blocked:阻塞状态,线程暂停执行,等待某个条件满足后再继续执行
  4. Waiting:等待状态,线程等待其他线程的通知,不会自动恢复运行
  5. Timed Waiting:定时等待状态,线程等待其他线程的通知,等待一段时间后会自动恢复运行
  6. Terminated:终止状态,线程执行完毕或者抛出异常后处于此状态

Runnable状态是指线程正在执行中的状态。

import java.util.concurrent.TimeUnit;

//Runnable示例
class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("Runnable线程开始执行。。。");
        try{
            TimeUnit.SECONDS.sleep(5);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("Runnable线程执行结束。。。");
    }
}

public class Main {
    public static void main(String[] args){
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();

        while(thread.isAlive()){
            System.out.println("线程正在执行中。。。");
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        System.out.println("线程执行完毕。。。");
    }
}

四、Thread和Runnable的选择

一般来说,如果只是简单的单线程程序,可以直接继承Thread类;如果是多线程程序,或者需要继承其他类的情况下,建议采用实现Runnable接口的方式。

Thread类在实现Runnable接口的基础上进行了封装,提供了更多的线程操作方法,适用于需要控制线程的详细信息的高级应用。而Runnable接口则更为简洁,更为灵活。

//Thread示例
class MyThread extends Thread{
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
            try{
                sleep(500);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

//Runnable示例
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
            try{
                Thread.sleep(500);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

public class Main {
    public static void main(String[] args){
        //创建Thread对象并启动线程
        MyThread myThread = new MyThread();
        myThread.start();

        //创建Runnable对象并启动线程
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

五、总结

Java中的thread和runnable都是与线程有关的概念,其中thread是一个类,可以扩展Java类库,它在实现线程时必须重写run()方法;而runnable是一个接口,它只有一个run()方法需要重写。在实现线程时,通常使用Runnable接口。

Runnable接口相对于扩展Thread类更加灵活,因为Java是单继承的,如果扩展了Thread类那么该类就不能再扩展其他的类了,这给程序设计带来了极大的限制。另外,如果需要创建多个线程对象,那么要扩展Thread类需要去创建多个Thread的子类,而实现Runnable接口只需要创建多个Runnable类的实例对象即可。

线程的状态包括新建状态、就绪状态、阻塞状态、等待状态、定时等待状态和终止状态。Runnable状态指线程正在执行中的状态。

使用Thread类,则需要在类中直接实现run()方法;使用Runnable接口,需要在类中实现run()方法,并且需要创建一个Thread对象,将实现了Runnable接口的类传递给Thread对象的构造方法,并且调用start()方法启动线程。