Java中多线程、多线程的实现方式、同步代码块的方式
多线程
- 进程
- 线程
- 概念
- 目前的程序是单线程
- 线程的组成部分
- 代码实现多线程的方式
- 第一种方式
- 第二种方式
- 第三种方式 -- 线程池
- 第四种方式:Callable
- 线程状态
- 线程同步
- 临界资源
- 原子操作
- 线程同步
- 线程同步第一种方式:同步代码块
- 线程同步第二种方式:同步方法
- 线程同步第三种方式:Lock
- 死锁
进程
- 进程的概念
操作系统(OS)中正在执行的应用程序,目前操作系统允许多个进程同时工作,被称为多进程 - 多进程并发执行原理
宏观上并行(一起执行);微观上串行(一个一个的执行),哪一个进程获取CPU时间片该进程获取执行权
线程
概念
在进程中,可以同时执行多个任务,每一个任务可以说是为一个线程,线程是进程的工作单位
线程也被称为轻量级的进程
目前的程序是单线程
以main函数的开始为开始,以main 函数的结束为结束,这个线程被称为主线程(Java中只有能代码实现多线程)
线程的组成部分
(1) cup
获取cpu时间片
(2) 数据
栈空间独立,堆空间共享每一个线程都有自己的独有栈空间;所有线程共享同一堆空间
(3) 程序代码
利用Java代码实现多线程
代码实现多线程的方式
第一种方式
- 类继承java.lang.Thread类,同时覆盖run()方法
注意:线程任务定义在run方法中 - 创建线程对象
MyThread t = new MyThread();
- 开启线程
利用 start开启线程,jvm执行线程时会自动的 调用run方法
t.start();
第二种方式
- 类实现 java.lang.Runnable 接口,实现接口中 run() 方法
注意:实现run时,访问修饰符必须是 public ,任务代码定义在run方法中,当前类代表是任务类 - 创建目标对象
MyTarget tg = new MyTarget();
- 创建线程对象,同时将目标对象作为参数进行传递
Thread t = new Thread(tg);
- 开启线程:调用 start方法
t.start();
第三种方式 – 线程池
线程池
线程容器,将预先创建的线程对象存入到线程池中,只要将任务提交给线程池,会分配对象线程对象完成提交任务,线程池中的线程对象可以被重复使用好处
避免频繁的创建线程和销毁,从而提高空间利用和执行效率线程池常用的接口和类,位于 java.util.concurrent包中
3.1 Executor:线程池的顶级接口
3.2 ExecutorService:是 Executor 的子接口,线程池的核心接口- submit(Runnable task):将线程任务提交给线程池
submit(Callable<\T> task):将线程任务提交给线程池 - shutdown(): 关闭线程池,将线程池的线程对象全部销毁
3.3 Executors:获取线程池对象的工具类,其中方法基本都为静态方法
- static ExecutorService newFixedThreadPool(int n):获取一 个固定数量线程的线程池,参数指定线程池中线程对象的数量
- static ExecutorService newCachedThreadPool() :获取动 态数量线程对象的线程池,根据提交的任务需求,不够用时, 则自动完成线程创建
- submit(Runnable task):将线程任务提交给线程池
第四种方式:Callable
- Callable接口
位于 java.util.concurrent 包中,类似于Runnable接口的应用,对应的对象代表线程任务
注意: Callable是泛型接口,泛型约束了接口中方法的返回值的数据类型 - 接口中的方法
V call():带有返回值的方法,同时可以抛出 异常
Future< T> f= pool.submit(c1); - Future是存储submit提交任务执行之后的结果
利用 Future中的 get方法获取执行的结果
线程状态
- 初始状态
线程已被创建但尚未执行(start() 尚未被调用) - 可执行状态
线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它执行 - 死亡状态
正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果,但是不被推荐,前者会产生异常,后者是强制终止,不会释放锁 - 阻塞状态
线程不会被分配 CPU 时间,无法执行
static void sleep(long ms) :如果在某一个线程中调用 Thread.sleep方法,则此线程进入有限期等待状态(计时状态/休眠,单位ms), 同时释放cpu;但是不释放该线程拥有得到锁标记
public final join():允许其他线程加入到当前线程中(调用join方法语句所在的线程),让调用join方法的线程先执行,等待其他线程任务执行结束之后,再执行自身的任务
线程同步
临界资源
被多个线程共享的同一个对象,此对象被称为临 界资源
原子操作
不可分割的多步操作,被视为一个整体,其执行顺序和步骤不能被打破
线程同步
多线程并发时,为了保证临界资源的正确性,而不能破坏程序中的原子操作(线程同步目的就是为保证原子操作的整体性,从而达到临界资源最终数据的正确性)
线程同步第一种方式:同步代码块
- 同步代码块对临界资源对象加锁
synchronized( 临界资源对象){// 原子操作
}
- 定义位置
同步代码块定义在方法内部 - 执行的原理
线程执行过程中,遇到同步代码块,只有线 程获取临界资源对象锁标记时,才能执行同步代码块{}中的 内容,并且只有{}中内容全部执行完成,才能释放该线程拥 有的锁标记;如果临界资源对象的锁标记被其他线程占用, 该线程进入阻塞状态(Blocked状态-等着需要的锁标记释放, 去获取),直到拿到所需要的锁标记才从阻塞状态结束,同时 再获取到cpu资源,才能继续执行同步代码块{}中内容注意:线程同步时,不同的线程必须是抢占同一个对象锁 标记,才能达到线程同步的目的(原子操作不被破坏,临界资 源的正确性)
线程同步第二种方式:同步方法
修饰符 synchronized 返回值 方法名(形参列表){ // 原子操作
}
- 被 synchronized 修饰方法被称为同步方法
0 同步方法等价于同步代码块
修饰符 返回值类型 方法名(形参列表){ synchronized(this){// 方法中语句(包含原子操作)}
}
线程同步第三种方式:Lock
- Lock
接口,位于 java.util.concurrent.locks 包中,代表锁 - Lock中常用方法
- void lock():获取锁,如果被占用,则需要等待
- void unlock():释放锁
- 实现类
ReentrantLock
死锁
- 死锁现象:两个线程或是多个线程相互占用对方所需要的的 资源,而都不释放,导致彼此之间相互等待对方释放资源, 从而产生无限制的等待现象。
- 结果:出现死锁后,不会抛出异常,也没有任何提示,只是所有的线程都处于阻塞状态,如果没有外力介入,程序将无 法继续
- 解决方案
- 尽可能的调整加锁的方案
- 尽量避免同步的嵌套嵌套
- 可以采用线程间的通信,等待-通知
在Object类中有 wait(等待)-notify/notifyAll(通知)方法- wait():等待
- 让当前进入等待状态,释放cpu的同时,释放拥有的锁标记
- wait方法调用必须使用在调用它的对象所在的同步代码块中
synchronized(o){
o.wait();
}
- notify:通知
- notify():通知一个线程从等待状态结束
notifyAll():通知所有的线程从等待状态结束 - notify/notifyAll方法的调用必须在调用它的对象所在同步代码块中
synchronized(o){ o.notify();
}
- notify和notifyAll只是起到通知的作用,不会释放锁标记
注意:调用 wait方法的对象和调用notify的对象是同一对象 (临界资源)
整理不易,喜欢请点个赞!
编者微信:1014961803,添加时请备注"CSDN"
Java中多线程、多线程的实现方式、同步代码块的方式相关推荐
- 第三次学JAVA再学不好就吃翔(part116)--同步代码块
学习笔记,仅供参考,有错必纠 文章目录 多线程 设置线程的优先级 同步代码块 什么情况下需要同步 同步代码块 死锁 多线程 设置线程的优先级 设置线程优先级: package com.guiyang. ...
- java中你知道的这四种代码块吗?
点击上方蓝字关注我们 大家好,我是雄雄,今天给大家分享的是:java中的四种代码块 什么叫代码块? 代码块就是将多行代码封装到一个"{}"中,形成一个独立的代码区,这就构成了代码块 ...
- Java中this关键词与构造函数,构造代码块的理解
目录 一.构造函数的理解 1.一个类的创建 二.代码块的理解 三.this关键词的理解 一.构造函数的理解 1.一个类的创建 public class Person {String name; // ...
- Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】
视频+资料[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg 提取码:zjxs] Java基础--学习笔记(零起点打开java世界的大门)--博 ...
- java 代码块(局部代码块、实例代码块、静态代码块、同步代码块)
1 引言 代码块是类的成分之一:成员变量,方法,构造器,代码块,内部类. 在Java中,使用 { } 括起来的代码被称为代码块(Code block) 1.1 代码块的分类 根据其位置和声明的不同,可 ...
- 基本线程同步(五)使用Lock同步代码块
声明:本文是< Java 7 Concurrency Cookbook >的第二章,作者: Javier Fernández González 译者:许巧辉 校对:方腾飞 使用Lo ...
- (四)Java中的多线程之间实现同步+多线程并发同步
一.什么是线程安全问题 为什么有线程安全问题? 当多个线程同时共享同一个全局变量或静态变量,做写的操作(修改变量值)时,可能会发生数据冲突问题,也就是线程安全问题.但是做读操作时不会发生数据冲突问题. ...
- 草根方式学习java中的多线程
草根方式学习java中的多线程 下面有具体的代码和截图 源码点这里 多线程即在同一时间,可以做多件事情(说白了,就是齐头并进) 单线程就是按部就班 创建多线程有2种方式,分别是继承线程Thread类, ...
- java中实现多线程的三种方式
java中实现多线程的三种方式 1.实现多线程的方法: 在java中实现多线程的两途径:继承Thread类,实现Runable接口(Callable) 2.继承Thread类实现多线程: 继承类T ...
最新文章
- Nagios 监控实例部署
- 发布 SharePoint Server 2007 Starter Page
- 8月第一周国内搜索网站 排名顺序基本稳定
- 数据库事务原理详解-数据库隔离级别
- 模式对话框与非模式对话框的区别
- overflow妙用--去除默认滚动条,内容仍可滚动
- android+动态地图+效果图,Android百度地图绘制圆形,圆形半径可动态变化
- 【2021Java最新学习路线】java前端开发
- Swift3 获取系统音量和监听系统音量
- vue input只能输入正整数_前端开发:Vue中获取input输入框值的方法
- python贪心算法几个经典例子_贪心算法及几个经典例子
- 欢迎使用传真服务器系统,coFax传真服务器 OCR页面号码识别传真
- 当年,学姐把这份Java总结给我,让我在22k的校招王者局乱杀
- Unity小游戏算法分析与实现(Unity+XR+游戏开发+算法+MVC+斗地主+耳轮跳+见缝插针+王者荣耀+绝地求生+立钻哥哥+==)
- 学习前端——仿写哔哩哔哩直播部分
- AI萃取的5G咖啡,只有华为能调出这个味道
- Hbase 内置过滤器
- 郭禹缘:鲍威尔释放鹰派言论,国际黄金或跌势重启后市分析。
- iis7 winmail php,winmail+php的配置
- 论文笔记 计算机模型的贝叶斯校准 Bayesian calibration of computer models
热门文章
- 10.6 自注意力和位置编码
- max 图片无法拖入3ds_达尔文3号和超级玛丽3号max,怎么选?首选它!
- NVL和NVL2有什么区别,NULLIF 的使用.
- 写给通信人的“失业”生存指南
- Python运维常用的脚本,提高工作效率就靠它了
- 使用StopWath统计代码执行耗时方法
- C++中的char,char*,char[]
- [杂谈] 14. Catalan卡特兰数
- Visual Studio 2010各个版本比较
- python+requests接口测试