网站首页 > 精选教程 正文
线程和进程
进程就是一个内存中运行的应用程序
线程是当前进程中的一个执行任务(控制单元),负责当前进程中程序的执行
区别与联系
- 根本区别:进程是操作系统资源分配的基本单位,线程是处理器任务调度和执行的基本单位
- 包含关系:一个进程可以有多个线程,至少有一个
- 内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的
- 影响关系:一个进程崩溃后,在保护模式下,不会对其他进程产生影响,而一个线程崩溃后,整个进程都会死掉,所以多进程比多线程健壮
- 执行过程:每个进程都有独立的程序运行入口、顺序执行序列和程序出口,而线程不能独立执行,必须依存在应用程序中
线程的生命周期
- 新建:当程序创建一个线程后,线程就处于新建状态,此时由 JVM 为其分配内存,并初始化其成员变量的值
- 就绪:当线程对象调用start()方法后,线程就处于就绪状态,JVM 会为其创建方法调用栈和程序调度器,等待调度运行
- 运行:处于就绪状态的线程获得了 CPU,开始执行run()方法的线程执行体,此时该线程就处于运行状态
- start()和run()的区别
- start() 方法来启动线程,实现了多线程运行,无需等待run方法体代码执行完毕,可以直接继续执行下面的代码
- 调用start()方法启动线程,线程会进入就绪状态,而非运行
- 方法run()被称为线程体,包含了要执行线程的内容,线程会进入运行状态,执行run方法体中的代码,方法运行结束,线程终止,CPU 再调度其他线程
- 阻塞:线程因为某种原因放弃了 CPU 使用权,暂时停止运行,此时线程处于阻塞状态
- 等待阻塞:运行的线程执行wait()方法,JVM 会将该线程放入等待队列中
- 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程所占用,则 JVM 会将该线程放入锁池(lock pool)中
- 其他阻塞:运行的线程执行sleep(long ms)或join()方法,或发出了I/O请求时,JVM 会将线程设置为阻塞状态。 当sleep()运行超时、join()等待线程终止或超时、或者I/O处理完毕时,线程可重新转入可运行状态
- sleep()和wait()的区别
- sleep()方法是属于 Thread 类中的,而wait()方法则是属于 Object 类中
- sleep()方法导致了程序暂停执行指定的时间,让出 CPU 给其他线程,但是他的监控状态仍然保持,当指定时间到了又会回到运行状态;在调用sleep()的过程中,线程不会释放对象锁
- 调用wait()方法时,会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后,本线程才进入对象锁定池准备获取对象锁进入运行状态
- 死亡:线程结束后就是死亡状态,会以以下三种方式结束
- 正常结束:run()或者call()方法执行完成,线程正常结束
- 异常结束:线程抛出一个未捕获的Exception或Error
- 调用stop:直接调用该线程的stop()方法来结束线程(该方法容易导致死锁,不推荐使用)
多线程
创建多线程方式
- 继承Thread类
?通过继承 Thread 类,重写其run()方法,run()方法中定义了线程执行的具体任务,创建该类的实例后,调用其start()方法来启动线程 - Thread 本质上是实现了 Runnable 接口的一个实例,代表线程的一个实例。
- public class ThreadTest extends Thread{ @Override public void run() { System.out.println("ThreadTest"); } } public class Main { public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); threadTest.start(); } }
- 实现Runnable接口
?实现 Runnable 接口后,通过重写其run()方法,然后将此 Runnable 对象作为参数传递给 Thread 类的构造器,创建 Thread 对象后,调用其 start()方法启动线程 - 如果自己的类已经继承了一个类,由于Java是单继承的,所以没法用第一种方式,就可以通过实现 Runnable 接口创建多线程,在 Runnable 接口中只有一个 run()方法
- public class ThreadTest implements Runnable{ @Override public void run() { System.out.println("Runnable"); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new ThreadTest()); thread.start(); } }
- 基于线程池的方式(Executor框架)
?这是种更高效的线程管理方式,避免了频繁创建和销毁线程的开销,可以通过 Executor 类的静态方法创建不同类型的线程池 - public class ThreadTest implements Runnable{ @Override public void run() { System.out.println("Executor"); } } public class Main { public static void main(String[] args) { // 创建固定大小的线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { // 提交任务到线程池执行 executorService.submit(new ThreadTest()); } // 关闭线程池 executorService.shutdown(); } }
三种方式的优缺点
继承Thread类
- 优点:编写简单,如果要访问当前线程,无需使用Thread.currentThread()方法,直接使用this即可
- 缺点:Java的单继承,在继承了Thread类后,不能再继承其他类了,有局限性
实现Runnable接口
- 优点:在实现了接口后,仍然可以继承其他类。在这种情况下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程处理同一份资源的情况,从而将CPU代码和数据分开,形成清晰的模型
- 缺点:编程较为复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法
线程池(Executor框架)
- 优点:线程池可以重用预先创建的线程,避免了线程创建和销毁的开销,提高程序的性能,对于快速响应的并发请求,线程池可以迅速提供线程来处理任务,减少等待时间。并且线程池可以有效控制运行的线程数量,防止创建过多的线程导致系统资源被耗尽(内存溢出),节约系统资源,可以最大化CPU利用率和系统吞吐率
- 缺点:增加了程序复杂度,特别是涉及到线程池参数调整和故障排查时,错误的配置可能导致资源耗尽、死锁等问题
四种线程池
Java中线程池的顶级接口是Executor但严格意义上,Executor并不是一个线程池,它只是一个执行线程的工具,真正的线程池接口是ExecutorService
- newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool: 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool:创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor:返回一个线程池(单一线程),在其他线程死后(或发生异常时),重新启动一个线程代替原来的线程执行下去。
- 上一篇: java多线程编程,面试真的躲不开!
- 下一篇: 控制线程的执行顺序
猜你喜欢
- 2025-01-02 Java 多线程面试秘籍:25 道题全攻略
- 2025-01-02 Java 线程和操作系统的线程有啥区别?
- 2025-01-02 Java线程唤醒与阻塞的常用方法
- 2025-01-02 JAVA多线程实现的四种方式
- 2025-01-02 两万字带你了解Java多线程(详细大总结)
- 2025-01-02 java线程和线程池
- 2025-01-02 java线程池闭坑指南
- 2025-01-02 Java多线程引发的性能问题以及调优策略
- 2025-01-02 深入解读-全流程分析Netty设计思路与实践
- 2025-01-02 Java多线程实战|CountDownLatch原理介绍及使用场景
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)