线程
概念
Java中,线程是程序执行的最小单位,它是进程的一个执行流,也是CPU调度和分配的基本单位。每个进程都可以运行多个线程,这些线程共享进程的内存块,但每个线程都有自己的堆栈和局部变量。
Java中的线程有两种类型:用户线程和守护线程。用户线程是程序的主要执行部分,而守护线程则是在后台运行的线程,用于执行一些支持性的任务,如垃圾回收。当所有用户线程都结束时,守护线程也会随JVM一起退出。
创建线程
一般创建线程有两种方式:
继承java.lang.Thread
类并重写run
方法。这种方式下,直接创建一个Thread类的子类,并重写其run
方法。在run
方法中编写线程要执行的代码。然后,创建一个该子类的实例,并调用其start
方法来启动线程。需要注意的是,不能直接调用run
方法,否则只是在普通的方法调用中执行了线程
代码,而没有启动新的线程。
实现java.lang.Runnable
接口并重写run
方法。这种方式下,我们创建一个实现了Runnable
接口的类,并重写其run
方法。然后,创建一个Thread
类的实例,并将该Runnable
对象作为参数传递给Thread
类的构造函数。最后再调用Thread
对象的start
方法来启动线程。
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start(); // 启动线程
new Thread(new MyRunnable()).start(); // 创建并启动线程
}
}
// 法一
class MyThread extends Thread {
@Override
public void run() {
// 线程执行的代码
System.out.println("MyThread is running!");
}
}
// 法二
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的代码
System.out.println("MyRunnable is running!");
}
}
单线程与多线程
单线程指的是程序在执行过程中,按照连续的顺序执行代码,前面的任务必须完成后,后面的任务才会开始执行。单线程的执行方式相对简单,系统稳定性较高,扩展性强,软件资源丰富,多用于点对点的服务。例如,当处理时间短或者启动频率高的服务时,通常使用单线程。
比如我们刚刚只启动了一个线程输出到控制台;
多线程则是指从软件或硬件上实现多个线程并发执行的技术。多线程程序能够将工作拆分到多个软件线程,这些线程可以由不同的CPU内核并行处理,从而提高整体处理性能。当程序包含复杂的计算任务,或者需要处理速度较慢的外围设备(如打印或网络操作)时,通常会使用多线程。此外,当程序需要同时完成多项任务,或者需要提高程序的响应速度时,也会使用多线程。
比如一个网站同时有100个人浏览,那么服务器就要启动多线程来运行,使得每个用户不需要等待。如果这里还是用单线程,那么必然导致有人会等前边的人访问完才能访问,所以要使用多线程,让每个用户的线程都基本无需等待就能访问到。
进程
进程(Process)是操作系统进行资源分配和调度的基本单位,它是程序的一次执行过程。一个进程包含一个运行中的程序及其数据、系统资源和线程等。进程和程序的区别在于,程序是一组静态的指令集合,而进程是程序的一次动态执行过程。进程具有动态性、并发性、独立性和结构性的特点。
例如打开QQ程序,QQ就是一个进程,QQ进程中可以有多个线程。
下图中我们看到有4个名为QQ.exe的进程,但是下面的线程窗口(Thread)中与QQ.exe相关的不止4个
线程与进程的区别
线程与进程的主要区别:
资源拥有:进程是拥有资源的一个独立单位,系统会给进程分配独立的内存空间和其他资源,如文件句柄、网络连接等。而线程是进程的一部分,它共享进程所拥有的资源,包括内存空间、文件句柄等。因此,线程之间共享数据变得更容易,但同时也需要注意同步和互斥问题。
执行方式:每个进程都有自己独立的执行环境和执行序列,系统通过进程切换来实现不同进程之间的并发执行。而线程是进程中的执行单元,多个线程共享同一个进程的地址空间,线程之间通过共享进程的资源来实现并发执行。线程的执行是由进程来启动和管理的,每个线程都有一个线程ID、程序计数器、寄存器集合和栈等执行上下文。
系统开销:由于进程拥有独立的资源,因此在创建、切换和销毁进程时,系统需要分配和回收大量的资源,开销较大。而线程共享进程的资源,创建、切换和销毁线程的开销相对较小,因此更适合用于实现大量的并发执行。
安全性:进程是独立的执行环境,一个进程出现问题不会影响其他进程的执行,因此多进程程序更加安全、生命力更强。但是,线程之间的共享数据可能会导致同步和互斥问题,如果处理不当,可能会出现数据不一致、死锁等问题,因此多线程程序需要更加小心地设计和实现。