"这篇笔记详细介绍了Java中的四种多线程创建方法,包括进程和线程的概念,以及并行与并发的差异。同时,讲解了如何通过继承Thread类、实现Runnable接口以及使用ExecutorService、Callable、Future来创建多线程程序,并强调了前两种方式无法返回结果,而最后一种方式支持有返回值的线程执行。"
在计算机科学中,程序是一组指令的集合,它在特定的语言下编写,用于完成特定的任务。当程序运行时,操作系统会为其创建一个进程,这可以看作是程序的一次动态执行实例,是资源分配的基本单位。每个进程都有独立的内存空间,确保不同进程之间的数据隔离。
线程则是进程内的一个执行路径,是调度和执行的最小单位。相比进程,线程更轻量级,它们共享同一进程的内存空间,拥有独立的程序计数器、栈和局部变量,因此线程切换的开销相对较小。
并行与并发是多任务处理的两个关键概念。并行是指多个CPU同时执行多个任务,而并发则是在单个CPU上通过时间片轮转的方式,让多个任务看似同时执行。在单核CPU系统中,实际上实现的是并发,而在多核或多CPU系统中,可以实现真正的并行。
Java提供了多种创建多线程的方式:
1. 继承Thread类:创建一个类扩展自Thread类,重写run()方法,然后创建该类的实例并调用start()方法启动线程。这种方式简单直观,但因为继承限制了类的扩展性。
2. 实现Runnable接口:创建一个类实现Runnable接口,实现run()方法,然后将Runnable对象作为参数传递给Thread类的构造函数,创建Thread对象并调用start()。这种方式避免了类的继承限制,更利于多态性。
3. 使用ExecutorService:Executor框架提供了一种更高级的线程管理方式。可以通过Executors类获取ExecutorService实例,然后使用submit()方法提交Runnable或Callable任务,ExecutorService会根据配置自动管理线程的生命周期。
4. 结合Callable和Future:Callable接口允许创建返回结果的线程,其call()方法代替run()方法。Future接口用于获取Callable任务的结果。通过ExecutorService的submit()方法提交Callable任务,返回的Future对象可以用来获取或检查任务结果。
每种方式都有其适用场景,理解这些概念和方法对于编写高效、可靠的多线程Java程序至关重要。选择适当的方式取决于具体的需求,如是否需要返回结果、线程管理的复杂性以及代码的可维护性等因素。