Java多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个任务,提高了程序的并发性和效率。在Java中,实现多线程主要有两种方式:继承`Thread`类和实现`Runnable`接口。
1. 继承`Thread`类:
当一个类直接继承`Thread`类时,该类就是一个线程类。你需要重写`run()`方法,将线程要执行的任务放入`run()`方法中。然后通过创建该线程类的实例并调用`start()`方法启动线程。这种方式的优点是代码结构清晰,直接继承线程类。但是,由于Java不支持多重继承,如果该类需要继承其他类,这种方式就会受到限制。
2. 实现`Runnable`接口:
这种方式更为灵活,类可以实现多个接口,从而避免了单继承的限制。你需要创建一个实现`Runnable`接口的类,并实现`run()`方法。然后将这个实现类的实例传递给`Thread`类的构造器,创建`Thread`对象,再调用`start()`方法启动线程。这种方式可以更好地实现代码的复用,多个线程可以共享同一个`Runnable`实例,从而实现资源的共享。
共同点:
无论选择哪种方式,都需要通过`Thread`类来创建线程,并调用`start()`方法来启动线程。`start()`方法会调用`run()`方法,使得新线程开始执行任务。
不同点:
- 继承`Thread`类时,类只能直接继承`Thread`,无法同时继承其他类,而实现`Runnable`接口则不受此限制。
- 如果需要多个线程执行相同的任务,实现`Runnable`接口的方式更节省资源,只需要一个`Runnable`实例,可以创建多个`Thread`对象共享。
示例代码:
- 示例1中,`MyThread`类继承了`Thread`,在`main`方法中创建了三个`Runnable`实例并分别创建了三个`Thread`对象。每个`Thread`对象调用`start()`启动线程。
- 示例2中,`MyThread1`类实现了`Runnable`接口,同样在`main`方法中创建了三个`Thread`对象,但它们共享同一个`Runnable`实例。
线程的状态:
线程有五种基本状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、终止(Terminated)。线程通过`start()`方法进入就绪状态,由JVM调度进入运行状态,可能因等待锁或其他资源而变为阻塞状态,当任务执行完毕后,线程进入终止状态。
多线程的主要用途是提高系统的并发性,使程序在等待某个操作完成时可以执行其他任务,而不是浪费CPU资源。在Java中,通过合理的多线程设计,可以有效地提升程序的执行效率,尤其是在I/O密集型或计算密集型的任务中。同时,多线程也带来了线程安全问题,如竞态条件、死锁等,需要开发者通过同步机制如`synchronized`关键字、`Lock`接口等来解决。