Java中的多线程编程(超级详细总结)
* *首先,线程和多线程的概念
线程,即单线程,是一个程序的执行线索和路径,是程序使用cpu的最小单位 。线程本身不能运行,只能在程序中运行,线程依赖于程序的存在 。
从字面上看,多线程就是从多个单线程执行多个任务 。在Java编程中,它提供了对多线程编程的内置支持 。多线程是多任务处理的一种特殊形式,但它使用的cpu资源较少 。多线程可以满足程序员写出高效的程序来充分利用CPU 。
第二,线程和进程的关系
进程:进程包括由操作系统分配的内存空,并包含一个或多个线程 。线程不能独立存在,它必须是进程的一部分 。一个进程一直运行,直到所有非守护进程线程都运行完毕 。线程是指流程中控制流的单个序列 。多个线程可以在一个进程中并发,每个线程并行执行不同的任务 。
①进程是指运行在内存中的一个应用,每个进程都有自己独立的内存空,即process 空或(virtual 空) 。进程独立于线程而存在,一个进程中可以启动多个线程 。例如,在Windows系统中,一个正在运行的exe就是一个进程 。
②线程是指一个流程中的一个执行流程,其中可以运行多个线程 。例如,许多线程可以在java.exe进程中运行 。一个线程始终属于一个进程,它没有自己的虚拟地址空,所以它与进程中的其他线程共享分配给该进程的所有资源 。
“同时”执行是人的感觉,实际上是在线程之间轮换执行 。(这句话简洁地阐述了多线程的实现机制)
③进程在执行时有独立的内存单元,进程有独立的地址空,而多个线程共享内存,大大提高了程序的运行效率 。
④执行过程中线程和进程还是有区别的 。每个独立的线程都有一个程序运行的入口、一个顺序执行序列和一个程序出口 。但是线程不能独立执行,所以必须由应用程序提供的多个线程来控制 。
⑤进程是一个程序在某个数据集上具有一定独立功能的运行活动 。进程是系统中用于资源分配和调度的独立单元 。
⑥线程是一个进程的实体,是CPU调度和分派的基本单位,比一个进程小,可以独立运行 。基本上,一个线程并不拥有系统资源,只是拥有一些运行所必需的资源(比如程序计数器、一组寄存器和堆栈),但它可以与属于同一进程的其他线程共享一个进程所拥有的所有资源 。
线程有自己的栈和局部变量,但是线程之间没有单独的地址空间空 。一个线程包含以下内容:
(1)指向当前执行的指令的指令指针;(2)一个堆栈;(3)一组寄存器值,其定义了描述执行线程的处理器状态的一部分值;(4)私有数据区 。
总而言之:
一个程序至少有一个进程,一个进程至少有一个线程 。线程的划分尺度小于进程,使得多进程程序的并发性高 。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率 。线程在执行过程中与进程还是有区别的 。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口 。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制 。从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行 。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配 。这就是进程和线程的重要区别 。
在Java中,每次程序运行时至少会启动两个线程:一个是主线程,另一个是垃圾收集线程 。因为每次用java命令执行一个类,实际上就启动了一个JVM,每个JVM实际上都启动了操作系统中的一个进程 。
第三,线程的生命周期
线程是一个动态执行的过程,也有一个从生到死的过程 。下图显示了线程的完整生命周期 。
1)新状态:在通过使用new关键字和线程类或其子类建立线程对象之后,线程对象处于新状态 。它保持这种状态,直到程序开始()这个线程 。
2)就绪状态:当线程对象调用start()方法时,线程进入就绪状态 。就绪线程在就绪队列中,等待JVM中线程调度器的调度 。
3)运行状态:如果就绪状态的线程获取了CPU资源,就可以执行run(),然后线程就处于运行状态了 。正在运行的线程是最复杂的,它可以被阻塞、就绪和死亡 。
4)阻塞状态:如果一个线程执行了sleep、suspend等方法,那么在失去所占用的资源后,就会从运行状态进入阻塞状态 。您可以在睡眠时间结束或获取设备资源后重新进入就绪状态 。它可以分为三种类型:
①等待阻塞:处于运行状态的线程执行wait()方法,使线程进入等待阻塞状态 。
②同步阻塞:线程获取同步的同步锁失败(因为同步锁被其他线程占用) 。
③其他阻塞:当通过调用线程的sleep()或join()发出I/O请求时,线程会进入阻塞状态 。当sleep()状态超时时,join()等待线程终止或超时,或者I/O处理完成,线程再次进入就绪状态 。
5)死状态:当一个正在运行的线程完成它的任务或者其他终止条件发生时,线程会切换到终止状态 。
四 。多线程的目的和意义
多线程的意义:其实任何程序的执行都需要cpu的执行权,由cpu决定执行哪个程序 。那么多线程的存在其实就是“充分利用cpu资源” 。当某个线程的处理不需要占用cpu,并且处理I/O时,就给了其他需要占用cpu资源的线程获取cpu资源的机会 。从根本上说,这就是多线程编程的目的 。
多线程的用途:与大多数其他编程语言不同,Java本身有内置的多线程支持 。使用多线程可以帮助我们最大限度的利用cpu,编写高效的程序,最小化空空闲时间,这对于Java运行的交互式网络环境是必不可少的,因为空空闲时间是公共的 。比如网络的传输效率远低于计算机的处理速度,本地文件系统资源的读写速度远低于cpu的处理能力 。做多线程,充分利用这些空空闲时间 。
五、线程的实现 。
①继承线程类:
使用thread类实现多线程代码,需要重写run()方法,但是重写run()方法后,只使用Thread类在main函数中创建对象,然后调用start()方法 。
这里你可能会问,为什么不直接调用重写后的run()方法呢?而是使用start()方法启动线程的操作?
这里我简单回答一下 。首先,方法可以由对象执行 。run()方法,但它要么是多线程方法,要么是公共方法 。若要实现多线程,必须使用对象 。start()方法 。Java中真正的多线程是start中的start()方法,run()方法只是一个普通的方法 。
【线程的概念和特点 线程有哪些】②实现可运行接口:
③继承线程类的方法和实现Runnable接口的方法的联系和区别:
(1)1)Thread类本身也实现了Runnable接口,所以也实现了Runnable接口中的run方法 。
(2)当使用继承的Thread类实现线程时,我们需要重写run方法,因为Thread类中的run方法本身什么也不做 。
(3)在实现Runnable接口实现线程时,我们需要重写run方法,然后使用新的Thread(Runnable)方法生成线程对象 。此时,线程对象中的run方法将执行我们自己实现的Runnable接口中的run方法 。
推荐阅读
- 钢琴品牌有哪些牌子 钢琴的品牌有哪些
- access修改报表标题 access数据库修改报表微标的操作方法
- 十大平民纯粮酒 纯粮食酒有哪些
- 疝气不治会有什么后果 疝气症状有哪些
- word文档转pdf后公章变黑色 word文档转成pdf时图章变为黑白色的处理方法
- 软装样板房 软装有哪些
- 基本全是肉的动漫 有哪些肉肉的动漫
- word表格边框显示不全跨页面显示的解决方法 word表格边框显示不全跨页面显示的解决方法
- word自动补齐括号设置取消的操作方法 word自动补齐括号设置取消的操作方法