多线程01,线程基础知识
多线程基础知识
目录介绍
1.进程概述及多进程的意义[理解]
- 1.1 线程和进程
- 1.2 进程概述
- 1.3 多进程的意义
2.线程的概述和多线程的意义[理解]
- 2.1 什么是线程
- 2.2 多线程有什么意义
- 2.3 并行和并发
3.JVM运行原理以及JVM启动的线程探讨[理解]
- 3.1 Java程序运行原理
- 3.2 JVM的启动是多线程的吗
4.多线程程序实现的方式[掌握]
- 4.1 多线程程序实现的方式【重点】
- 4.1.1 第一种方式:是类继承Thread
- 4.1.2 第二种方式:是实现接口Runnable
- 4.2 多线程两种方式的区别
- 4.3 几个小问题探索
- 4.4 匿名内部类的方式实现多线程程序
5.线程调度
- 5.1 线程的调度问题
- 5.2 线程有两种调度模型
6.线程控制
- 6.1 线程控制之休眠线程
- 6.2 线程控制之加入线程
- 6.3 线程控制之礼让线程
- 6.4 线程控制之守护线程
- 6.5 线程控制之中断线程
7.案例分析
- 7.1 继承Thread类的方式卖电影票案例
- 7.2 实现Runnable接口的方式卖电影票
- 7.3 买电影票出现了同票和负数票的原因分析
- 7.4 线程安全问题的产生原因分析
- 7.5 同步代码块的方式解决线程安全问题
1.进程概述及多进程的意义[理解]
1.1 线程和进程
- 要想说线程,首先必须得聊聊进程,因为线程是依赖于进程存在的。
1.2 进程概述
- 什么是进程呢?通过任务管理器我们就可以看到进程的存在。
- 概念:进程就是正在运行的程序,是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。
1.3 多进程的意义
- 单进程计算机只能做一件事情。而我们现在的计算机都可以一边玩游戏(游戏进程),一边听音乐(音乐进程),所以我们常见的操作系统都是多进程操作系统。比如:Windows,Mac和Linux等,能在同一个时间段内执行多个任务。
- 对于单核计算机来讲,游戏进程和音乐进程是同时运行的吗?不是。
- 因为CPU在某个时间点上只能做一件事情,计算机是在游戏进程和音乐进程间做着频繁切换,且切换速度很快,
- 所以,我们感觉游戏和音乐在同时进行,其实并不是同时执行的。多进程的作用不是提高执行速度,而是提高CPU的使用率。
2.线程的概述和多线程的意义[理解]
2.1 什么是线程
- 在一个进程内部又可以执行多个任务,而这每一个任务我们就可以看成是一个线程。是程序使用CPU的基本单位。
2.2 多线程有什么意义
- 多线程的作用不是提高执行速度,而是为了提高应用程序的使用率。
- 那么怎么理解这个问题呢?我们程序在运行的使用,都是在抢CPU的时间片(执行权),如果是多线程的程序,那么在抢到CPU的执行权的概率应该比较单线程程序抢到的概率要大.那么也就是说,CPU在多线程程序中执行的时间要比单线程多,所以就提高了程序的使用率.但是即使是多线程程序,那么他们中的哪个线程能抢占到CPU的资源呢,这个是不确定的,所以多线程具有随机性.
2.3 并行和并发
- 前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
- 后者是物理上同时发生,指在某一个时间点同时运行多个程序。
3.JVM运行原理以及JVM启动的线程探讨[理解]
3.1 Java程序运行原理
- Java命令会启动java虚拟机,启动JVM,等于启动了一个应用程序,也就是启动了一个进程。
- 该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。
3.2 JVM的启动是多线程的吗
- JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。
4.多线程程序实现的方式[掌握]
4.1 多线程程序实现的方式
- 4.1.1 第一种方式:是类继承Thread
第一种方式的步骤:
1: 定义一个类,让该类去继承Thread类
2: 重写run方法
3: 创建该类的对象
4: 启动线程public class ThreadDemo {public static void main(String[] args) {// 创建对象MyThread t1 = new MyThread() ;MyThread t2 = new MyThread() ;// 启动线程: 需要使用start方法启动线程, 如果我们在这里调用的是run方法,那么我们只是把该方法作为普通方法进行执行
// t1.run() ;
// t1.run() ;t1.start() ; // 告诉jvm开启一个线程调用run方法// t1.start() ; // 一个线程只能被启动一次t2.start() ;}
}public class MyThread extends Thread {@Overridepublic void run() {for(int x = 0 ; x < 1000 ; x++) {System.out.println(x);}}
}
- 4.1.2 第二种方式:是实现接口Runnable
实现多线程的第二中方式步骤:
1: 定义一个类,让该类去实现Runnable接口
2: 重写run方法
3: 创建定义的类的对象
4: 创建Thread的对象吧第三步创建的对象作为参数传递进来
5: 启动线程public static void main(String[] args) {// 创建定义的类的对象MyThread mt = new MyThread() ;// 创建Thread的对象吧第三步创建的对象作为参数传递进来Thread t1 = new Thread(mt , "张三") ;Thread t2 = new Thread(mt , "李四") ;// 启动线程t1.start() ;t2.start() ;
}public class MyThread implements Runnable {@Overridepublic void run() {for(int x = 0 ; x < 1000 ; x++) {System.out.println(Thread.currentThread().getName() + "---" + x);}}
}
4.2 多线程两种方式的区别
- run()方法只是调用了Thread实例的run()方法而已,它仍然运行在主线程上,而start()方法会开辟一个新的线程,在新的线程上调用run()方法,此时它运行在新的线程上。
4.3 几个小问题探索
- 4.3.1 为什么要重写run方法
- 可以在定义的类中,定义多个方法,而方法中的代码并不是所有的都需要线程来进行执行; 如果我们想让某一个段代码被线程,那么我们只需要将那一段代码放在run方法中。那么也就是说run方法中封装的都是要被线程执行的代码 ;
- run方法中的代码的特点: 封装的都是一些比较耗时的代码
- 4.3.2 线程能不能多次启动
- 一个线程只能被启动一次
- 4.3.2 run()和start()方法的区别
- 启动线程: 需要使用start方法启动线程, 如果我们在这里调用的是run方法,那么我们只是把该方法作为普通方法进行执行。
4.4 匿名内部类的方式实现多线程程序
- new Thread(){代码…}.start();
- new Thread(new Runnable(){代码…}).start();
5.线程调度
5.1 线程的调度问题
- 应用程序在执行的时候都需要依赖于线程去抢占CPU的时间片 , 谁抢占到了CPU的时间片,那么CPU就会执行谁
- 线程的执行:假如我们的计算机只有一个 CPU,那么 CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。
5.2 线程有两种调度模型
- 5.2.1 分时调度模型
- 所有线程轮流使用CPU的使用权,平均分配每个线程占用 CPU 的时间片
- 5.2.2 抢占式调度模型
- 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。Java使用的是抢占式调度模型。
6.线程控制
6.1 线程控制之休眠线程
- public static void sleep(long time) ;
- time表达的意思是休眠的时间 , 单位是毫秒
6.2 线程控制之加入线程
- public final void join()
- 等待该线程执行完毕了以后,其他线程才能再次执行
- 注意事项: 在线程启动之后,在调用方法
6.3 线程控制之礼让线程
- public static void yield():
- 暂停当前正在执行的线程对象,并执行其他线程。
- 线程礼让的原理是: 暂定当前的线程,然CPU去执行其他的线程, 这个暂定的时间是相当短暂的; 当我某一个线程暂定完毕以后,其他的线程还没有抢占到cpu的执行权 ; 那么这个是时候当前的线程会和其他的线程再次抢占cpu的执行权;
6.4 线程控制之守护线程
- public final void setDaemon(boolean on)
- 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。
- jvm会线程程序中存在的线程类型,如果线程全部是守护线程,那么jvm就停止。
6.5 线程控制之中断线程
- public final void stop():
- 停止线程的运行
- public void interrupt():
- 中断线程(这个翻译不太好),查看API可得当线程调用wait(),sleep(long time)方法的时候处于阻塞状态,可以通过这个方法清除阻塞
7.案例分析
7.1 继承Thread类的方式卖电影票案例
public class ThreadDemo {public static void main(String[] args) {/*** 需求:某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。*/// 创建3个线程对象SellTicktes t1 = new SellTicktes() ;SellTicktes t2 = new SellTicktes() ;SellTicktes t3 = new SellTicktes() ;// 设置名称t1.setName("窗口1") ;t2.setName("窗口2") ;t3.setName("窗口3") ;// 启动线程t1.start() ;t2.start() ;t3.start() ;}
}public class SellTicktes extends Thread {private static int num = 100 ;@Overridepublic void run() {/*** 定义总票数* * 如果我们把票数定义成了局部变量,那么表示的意思是每一个窗口出售了各自的100张票; 而我们的需求是: 总共有100张票* 而这100张票要被3个窗口出售; 因此我们就不能把票数定义成局部变量,只能定义成成员变量*/ // 模拟售票while(true) {if( num > 0 ) {System.out.println(Thread.currentThread().getName() + "正在出售" + (num--) + "张票");}}}
}
7.2 实现Runnable接口的方式卖电影票
public class SellTicektesDemo {public static void main(String[] args) {// 创建SellTicektes对象SellTicektes st = new SellTicektes() ;// 创建Thread对象Thread t1 = new Thread(st , "窗口1") ;Thread t2 = new Thread(st , "窗口2") ;Thread t3 = new Thread(st , "窗口3") ;// 启动线程t1.start() ;t2.start() ;t3.start() ;}
}public class SellTicektes implements Runnable {private static int num = 100 ;@Overridepublic void run() {while(true) {if(num > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (num--) + "张票");}}}
}
7.3 买电影票出现了同票和负数票的原因分析
- 讲解过电影院售票程序,从表面上看不出什么问题,但是在真实生活中,售票时网络是不能实时传输的,总是存在延迟的情况,所以,在出售一张票以后,需要一点时间的延迟。改实现接口方式的卖票程序,每次卖票延迟100毫秒
public class ThreadDemo {public static void main(String[] args) {// 创建3个线程对象SellTicktes t1 = new SellTicktes() ;SellTicktes t2 = new SellTicktes() ;SellTicktes t3 = new SellTicktes() ;// 设置名称t1.setName("窗口1") ;t2.setName("窗口2") ;t3.setName("窗口3") ;// 启动线程t1.start() ;t2.start() ;t3.start() ;}
}public class SellTicktes extends Thread {private static int num = 100 ;@Overridepublic void run() {// 模拟售票while(true) {if( num > 0 ) {try {Thread.sleep(100) ;} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在出售" + (num--) + "张票");}}}
}
7.4 线程安全问题的产生原因分析
- 7.4.1 首先想为什么出现问题?
- 是否是多线程环境,是否有共享数据,是否有多条语句操作共享数据
- 7.4.2 如何解决多线程安全问题呢?
- 基本思想:让程序没有安全问题的环境。怎么实现呢?把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。
7.5 同步代码块的方式解决线程安全问题
- 7.5.1 同步代码块的格式
- 同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能
synchronized(对象){需要同步的代码;}
- 7.5.2 同步代码块优势和劣势
- 同步的好处:同步的出现解决了多线程的安全问题。
- 同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
多线程01,线程基础知识相关推荐
- JavaSE基础二十:Java 多线程(线程基础知识、Java 多线程、Java 实现多线程(继承 Thread 类、实现 Runnable 接口、实现 Callable 接口))
本章目录 1.基础知识准备 2.Java 多线程概述 3.Java 实现多线程 3.1.继承 Thread 类 如何开启新线程 Thread 类常用方法 多线程中的同步 Thread 类同步方法 多线 ...
- 01.线程基础知识初识
1.进程与线程 进程与线程的由来: 计算机cpu工作原理,操作系统调度单核cpu时其实是在不停的切换任务,因为cpu同一时间只能做一件事,而且cpu做事速度很快,往往在完成一件任务时需要等待其他零件完 ...
- 进程和线程基础知识(已经是最详细的啦)
进程和线程基础知识 文章目录 进程和线程基础知识 一.前言 二.进程 1.引入 2.并发和并行有什么区别? 3.进程与程序的关系的类比 4.进程的状态 5.进程的控制结构 6.进程的控制 7.进程的上 ...
- Linux进程管理:进程和线程基础知识
<Linux进程管理:进程和线程基础知识> <Linux-进程管理> <C语言进程的内存地址空间分配> <进程和线程模型> <(1)Linux进程 ...
- 快速get进程、线程基础知识
前言 为了方便大家理解进线程的工作流程及运行状态,先来看一篇小故事: 我们写好的一行行代码,为了让其工作起来,我们还得把它送进城(进程)里,那既然进了城里,那肯定不能胡作非为了. 但是城里有城里的规矩 ...
- 线程基础知识系列(三)线程的同步
本文是系列的第三篇,前面2篇,主要是针对单个线程如何管理,启动等,没有过多涉及多个线程是如何协同工作的. 线程基础知识系列(二)线程的管理 :线程的状态,控制,休眠,Interrupt,yield等 ...
- Java中的线程基础知识
Java中的线程基础知识 1.线程概念 线程是程序运行的基本执行单元.当操作系统(不包括单线程的操作系统,如微软早期的DOS)在执行一个程序时,会在系统中建立一个进程,而在这个进程中,必须至少建立一个 ...
- 线程基础知识——Windows核心编程学习手札系列之六
线程基础知识 --Windows核心编程学习手札系列之六 线程与进程一样由两部分构成:一是线程的内核对象,操作系统用它来对线程实施管理,也是系统用来存放线程统计信息的地方:二是线程堆栈,用于维护线程在 ...
- Windows核心编程 第六章 线程基础知识 (上)
第6章 线程的基础知识 理解线程是非常关键的,因为每个进程至少需要一个线程.本章将更加详细地介绍线程的知识.尤其是要讲述进程与线程之间存在多大的差别,它们各自具有什么作用.还要介绍系统如何使用线程内核 ...
- 「JAVA」通过抢气球案例,来梳理线程基础知识
程序在没有流程控制的前提下,代码都是从上而下逐行依次执行的.基于这样的机制,如果我们使用程序来实现边打游戏,边听音乐的需求时,就会很困难:因为按照执行顺序,只能从上往下依次执行:同一时刻,只能执行听音 ...
最新文章
- mysql根据时间取前后几秒,几分钟,几小时,几天,几月,几年
- [Android] Android MVP 架构下 最简单的 代码实现
- 剑指 Offer 59 - I. 滑动窗口的最大值
- yii框架安装及环境配置!!!
- 爬虫 spider06——解析数据
- 关于C++中的友元函数的总结
- MacBook/MacOS如何写入MacBook特有的符号(例如:⌘/⌥/⎋/⇪)
- 含有任意量词与存在量词的最值问题
- 跨境电商自建独立站CMS
- 4800包括了路线坐标正反算、竖曲线、超高加宽、边坡放样及断面计算等程序。
- 由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题
- C++使用类和对象(谭浩强9.8-9.14)
- LeetCode:14. Longest Commen Prefix(Easy)
- 够壕!支付宝新楼“蚂蚁Z空间”启用 网友:公司缺人吗
- Redis 查看端口使用情况
- selenium 如何在已打开的浏览器上直接自动化脚本
- 验证码机制之验证码自动识别
- 51单片机中断与计时器
- Cris 小哥哥的大数据项目之 HBase 模拟微博核心功能
- 米小圈上学记这本书太烂了