摘要:一个进程可以拥有多个线程,一个线程必须有一个父进程。线程是独立运行的,它并不知道进程中是否还有其他的线程存在。线程的调度和管理由进程本身负责完成。因此多线程实现多任务并发比多线程的效率高。
一个任务通常就是一个程序,每个运行中的程序就是一个进程。当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程。
进程定义:
当一个程序进入内存运行时,即变成一个进程。进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。
进程的特点:独立性:是系统独立存在的实体,拥有自己独立的资源,有自己私有的地址空间。在没有经过进程本身允许的情况下,一个用户的进程不可以直接访问其他进程的地址空间。
动态性:进程与程序的区别在于:程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集和,进程中加入了时间的概念。进程具有自己的生命周期和不同的状态,这些都是程序不具备的。
并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会相互影响。
并行性和并发性并行:指在同一时刻,有多条指令在多个处理上同时执行。(多核同时工作)
并发:指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。(单核在工作,单核不停轮询)
线程多线程扩展了多进程的概念,使得同一个进程可以同时并发处理多个任务。
线程(Thread)也被成为轻量级的进程,线程是进程执行的单元,线程在程序中是独立的、并发的执行流
当进程被初始化后,主线程就被创建了。绝大数应用程序只需要有一个主线程,但也可以在进程内创建多条的线程,每个线程也是相互独立的。
一个进程可以拥有多个线程,一个线程必须有一个父进程。
线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不拥有系统资源,它与父进程的其他线程共享该进程所拥有的全部资源,因此编程更加方便。
线程是独立运行的,它并不知道进程中是否还有其他的线程存在。线程的执行是抢占式的,即:当前运行的线程在任何时候都有可能被挂起,以便另外一个线程可以运行。
一个线程可以创建和撤销另一个线程,同一个进程中多个线程之间可以并发执行。
线程的调度和管理由进程本身负责完成。
归纳而言:操作系统可以同时执行多个任务,每个任务就是进程;进程可以同时执行多个任务,每个任务就是线程
多线程的优点:
进程之间不能共享内存,但线程之间共享内存非常容易
系统创建进程要为该进程重新分配系统资源,但创建线程的代价则小得多。因此多线程实现多任务并发比多线程的效率高。
Java语言内置了多线程功能支撑,简化了多线程的编程。
线程的创建和启动一、继承Thread类创建线程类
步骤:
① 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,称为线程执行体
② 创建Thread子类的实例,即创建了线程对象
③ 调用线程对象的start()方法来启动该线程
示例:
// 通过继承Thread类来创建线程类 public class FirstThread extends Thread { private int i ; // 重写run方法,run方法的方法体就是线程执行体 public void run() { for ( ; i < 100 ; i++ ) { // 当线程类继承Thread类时,直接使用this即可获取当前线程 // Thread对象的getName()返回当前该线程的名字 // 因此可以直接调用getName()方法返回当前线程的名 System.out.println(getName() + " " + i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { // 调用Thread的currentThread方法获取当前线程 System.out.println(Thread.currentThread().getName() + " " + i); if (i == 20) { // 创建、并启动第一条线程 new FirstThread().start(); // 创建、并启动第二条线程 new FirstThread().start(); } } } }
① 当Java程序开始运行后,程序至少会创建一个主线程,main()方法的方法体代表主线程的线程执行体
② 当线程类继承Tread类时,直接使用this即可以获取当前线程
③ 继承Thread类创建线程类,多个线程之间无法共享线程类的实例变量
二、实现Runnable接口创建线程类① 定义Runnable接口的实现类,并重写该接口的run()方法
② 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Tread对象,该Tread对象才是真正的线程对象
// 通过实现Runnable接口来创建线程类 public class SecondThread implements Runnable { private int i ; // run方法同样是线程执行体 public void run() { for ( ; i < 100 ; i++ ) { // 当线程类实现Runnable接口时, // 如果想获取当前线程,只能用Thread.currentThread()方法。 System.out.println(Thread.currentThread().getName() + " " + i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 20) { SecondThread st = new SecondThread(); // ① // 通过new Thread(target , name)方法创建新线程 new Thread(st , "新线程1").start(); new Thread(st , "新线程2").start(); } } } }
① 实现Runnable接口创建线程类,必须通过Thread.currentThread()方法来获得当前线程对象
② 实现Runnable接口创建线程类,多个线程可以共享线程类的实例变量
三、使用Callable和Future创建线程Callable接口提供了一个call()方法,call()方法比run()方法更强大:
① call()方法可以由返回值
② call()方法可以声明抛出异常
① 创建Callable接口的实现类,并实现call()方法,该call()方法作为线程执行体,且该call()方法有返回值
② 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值
③ 调用FutureTask对象的get()方法获得子线程执行结束的返回值
创建线程三种方式的对比:优点:
①实现的是接口,还可以继承其他类
② 多个线程可以共享同一个target对象,适合多个相同的线程来处理同一份资源的情况
缺点:
① 编程稍微复杂
② 获取当前线程必须用Thread.currentThread()方法来获得
优点:
①编程简单
② 获取当前线程,可以直接使用this来获得
缺点:
① 已经继承了Thread类,不能继承其他类
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69113.html
摘要:本文主要内容为简单总结中线程池的相关信息。方法簇方法簇用于创建固定线程数的线程池。三种常见线程池的对比上文总结了工具类创建常见线程池的方法,现对三种线程池区别进行比较。 概述 线程可认为是操作系统可调度的最小的程序执行序列,一般作为进程的组成部分,同一进程中多个线程可共享该进程的资源(如内存等)。在单核处理器架构下,操作系统一般使用分时的方式实现多线程;在多核处理器架构下,多个线程能够...
摘要:本篇博客主要针对虚拟机的晚期编译优化,内存模型与线程,线程安全与锁优化进行总结,其余部分总结请点击虚拟总结上篇,虚拟机总结中篇。 本篇博客主要针对Java虚拟机的晚期编译优化,Java内存模型与线程,线程安全与锁优化进行总结,其余部分总结请点击Java虚拟总结上篇 ,Java虚拟机总结中篇。 一.晚期运行期优化 即时编译器JIT 即时编译器JIT的作用就是热点代码转换为平台相关的机器码...
阅读 2738·2021-10-11 10:57
阅读 1569·2021-09-26 09:55
阅读 1310·2021-09-06 15:11
阅读 3447·2021-08-26 14:16
阅读 662·2019-08-30 15:54
阅读 535·2019-08-30 12:43
阅读 3290·2019-08-29 16:18
阅读 2565·2019-08-23 16:14