继承
Thread
类创建线程:- 这种方式是通过创建一个新的类,该类继承自
Thread
类,并重写run
方法。然后,通过创建该类的实例并调用其start
方法来启动线程。 - 优点:代码简单,易于理解。
- 缺点:由于Java是单继承的,继承
Thread
类后就不能再继承其他类了,这在一定程度上限制了类的扩展性。
- 这种方式是通过创建一个新的类,该类继承自
实现
Runnable
接口创建线程:- 这种方式是通过创建一个实现了
Runnable
接口的类,并实现其run
方法。然后,将该类的实例作为参数传递给Thread
类的构造器,创建Thread
对象并调用其start
方法来启动线程。 - 优点:由于Java支持接口的多实现,因此这种方式更具灵活性,可以继承其他类并实现
Runnable
接口。 - 缺点:相对于继承
Thread
类,代码稍显复杂。
- 这种方式是通过创建一个实现了
通过
Callable
和FutureTask
创建线程:Callable
接口类似于Runnable
接口,但它可以返回结果并且可以抛出受检异常(checked exception)。FutureTask
是Future
接口的一个实现,它包装了一个Callable
对象,可以提交给Executor
(如线程池)来执行。- 这种方式通常用于需要获取线程执行结果或处理受检异常的场景。
通过线程池创建线程:
- 线程池是提前创建好一批线程,并保存在池中。当有任务需要执行时,从池中取出一个线程来执行任务。这种方式可以显著提高资源的利用率和性能。
- Java中的
ExecutorService
接口提供了管理线程池的方法,如newFixedThreadPool
、newCachedThreadPool
等。 - 优点:提高资源利用率、性能;简化线程管理。
- 缺点:增加了代码的复杂性;需要合理配置线程池的大小以避免资源耗尽或性能下降。
关于Runnable
和Callable
的区别:
Runnable
的run
方法无返回值,而Callable
的call
方法有返回值。Callable
中可以抛出受检异常,而Runnable
不可以。Callable
和Runnable
都可以应用于executors
(执行器),但Thread
类只支持Runnable
。
关于Future
和FutureTask
:
Future
是一个接口,代表了一个异步执行的结果。它提供了检查执行是否完成、等待完成和获取执行结果的方法。FutureTask
是Future
接口的一个实现,它实现了一个可以提交给Executor
执行的任务,并且可以用来检查任务的执行状态和获取任务的执行结果。
最后,线程池是池化技术的一种典型实现,用于提高资源的利用率和性能。在编程中,线程池通常用于管理大量并发任务的执行。