当前位置: 首页 > news >正文

Java基础总结

1,Java JMM(java内存模型)

这个内存模型搞起来还是有点弯弯绕,一点点的整理吧。JMM的目的就是保证共享变量在多线程环境下的原子性,可见性,与有序性而定义的一组规范。这些问题的出现都跟CPU的设计有关系,CPU是计算机的运算核心所有的操作或者说指令都是在CPU里面运行的,而且CPU的运行效率超级高,比内存的运行速率还要高出几个数量级,做开发的肯定都知道内存比硬盘快几个数量级,会使用内存缓存来提高运行速率,但是使用了内存缓存就会出现数据不一致的问题,我们会采取各种措施来保证数据的一致性,这里不展开讨论缓存的问题。还是说回CPU,既然CPU的运行速率比内存快的多,设计者也设计了CPU的高速缓存来充分利用CPU的性能提高程序的运行效率。多了这个高速缓存,同样也会出现数据不一致的问题,于是就有了缓存一致性协议如MESI协议等,就是保证数据的一致性。各种操作系统运行在CPU等硬件之上同样要解决这个问题,于是不同的操作系统也有自己的内存模型。而java程序运行在JVM之上,而且支持平台一致,支持多线程并发,为了保证各个平台运行结果一致,保证共享数据在多线程环境下的一致有序,制定了JMM规范,所有的JVM都要遵从该规范,保证java程序的平稳高速运行。我们平时开发用到的(我现在接触到的)就是一个volatile和syncronized两个关键字,还有锁机制。当然还有其他原则,这里不涉及。而volatile的作用就是保证共享数据的可见性,使用的技术叫做内存屏障。内存屏障这个词听起来不是很好理解是英语直译,用中国话说就是内存数据的写入和读取的顺序以及方式,你不是有主内存还有cpu缓存还有什么堆内存栈内存吗?好一个内存屏障的指令可以规定数据从哪里读取,又该啥时同步。好了到这里了,一个 volatile 关键字的demo,贴在下面:

/*** volatile 可以保证共享变量的可见性,所谓可见性就是 保证变量的操作都是在共享堆内存中进行,而不是线程变量。*/
public class VolatileTest {private static boolean flag = false;private static volatile boolean volatileFlag = false;public static void main(String[] args) throws InterruptedException {new Thread(() -> {while (!flag) { //程序会在这里死循环,因为之后的代码虽然对该属性做了修改,但对于该线程不可见。}System.out.println("Flag is now true!");}).start();new Thread(() -> {while (!volatileFlag) { //使用volatile修饰的变量只要发生变化对所有线程可见。}System.out.println("volatileFlag is now true!");}).start();Thread.sleep(1000);flag = true;System.out.println("Flag is set to true!");volatileFlag = true;System.out.println("volatileFlag is set to true!");}
}
2,ThreadLocal 与 SimpleDateFormat

首先是平时经常使用的 SimpleDateFormat 是线程不安全的,我平时都是现用现new的,据说这样子有点浪费系统资源。查阅相关资料后发现还可以结合ThreadLocal来使用,就是将df对象绑定在线程上,在空间和效率之间取得一点平衡。ThreadLocal,这个东西设计的很奇怪。你本身是用来操作Thread类里面的threadLocalMap的,你叫个ThreadLocalMapUtils不比ThreadLocal好理解啊?总之这个类就是将一个对象绑定在线程上,不同的线程会创建不同的对象(也有可能是克隆如果实现了clone方法的话)比如下面的例子。也就是说所有线程不安全的类(变量)都可以绑定在ThreadLocal上面呗?


import java.text.DateFormat;
import java.text.SimpleDateFormat;/*** ThreadLocal 为每一个线程提供了独立的变量副本。也就是说 get() set() 方法是基于线程的,线程不一样获取到的对象就不一样。* 使用场景:* 适合保存和传递每个线程独立的数据,比如基于线程执行的用户信息,会话信息等,注意如果内部启用了新线程(子线程)会导致数据不一致。* 而且基于线程池的线程对象不会被回收,ThreadLocal变量也就不会被回收,所以使用完毕手动清除是个好习惯 threadLocal.remove();**/
public class ThreadLocalTest {static ThreadLocal<MyObject> threadLocal = ThreadLocal.withInitial(() -> {MyObject myObject = new MyObject();System.out.println(myObject);//com.kuafu.MyObject@22f71333 //com.kuafu.MyObject@29702e06 这里会执行两次,因为有两个线程来访问return myObject;});private static ThreadLocal<DateFormat> tlDf = ThreadLocal.withInitial(() -> {final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(simpleDateFormat);//java.text.SimpleDateFormat@4f76f1a0 //java.text.SimpleDateFormat@4f76f1a0return simpleDateFormat;});public static void main(String[] args) {final MyObject myObject = threadLocal.get();System.out.println(myObject);//com.kuafu.MyObject@22f71333new Thread("t1"){@Overridepublic void run() {final MyObject myObject1 = threadLocal.get();System.out.println(myObject1); //com.kuafu.MyObject@29702e06System.out.println(myObject == myObject1); //falseSystem.out.println(myObject.equals(myObject1)); //false}}.start();final DateFormat dateFormat = tlDf.get();System.out.println(dateFormat); //java.text.SimpleDateFormat@4f76f1a0new Thread("t1"){@Overridepublic void run() {final DateFormat dateFormat1 = tlDf.get();System.out.println(dateFormat1); //java.text.SimpleDateFormat@4f76f1a0System.out.println(dateFormat == dateFormat1); //false 这里看起来是个浅克隆?System.out.println(dateFormat.equals(dateFormat1)); //true}}.start();}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • html+css+js前端作业英雄联盟首页1个页面带js
  • 测试面试宝典(四十一)—— 接口自动化的优缺点
  • 关闭窗口工具类 - C#小函数类推荐
  • C++四种类型转换
  • 【课程总结】day19(中):Transformer架构及注意力机制了解
  • 测试类型分类
  • SQLite ORDER BY 语句
  • rust_mac环境安装
  • TypeScript声明文件
  • .ai域名是什么后缀?
  • Java 中的缓冲流
  • Animate软件基础:关于补间动画中的图层
  • 关于香橙派系统烧录,1.1.8或者1.1.10两个版本都无法启动Orangepi5
  • 数据库相关概念大全!
  • 如何优雅地重装系统:使用Ventoy实现系统安装All In One
  • 【Leetcode】101. 对称二叉树
  • CSS 专业技巧
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • ES6 ...操作符
  • JavaScript 一些 DOM 的知识点
  • JavaScript-Array类型
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 飞驰在Mesos的涡轮引擎上
  • 工作中总结前端开发流程--vue项目
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 精彩代码 vue.js
  • 王永庆:技术创新改变教育未来
  • 我是如何设计 Upload 上传组件的
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • Mac 上flink的安装与启动
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​TypeScript都不会用,也敢说会前端?
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #Java第九次作业--输入输出流和文件操作
  • #mysql 8.0 踩坑日记
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (4)(4.6) Triducer
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (LLM) 很笨
  • (独孤九剑)--文件系统
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (十三)Maven插件解析运行机制
  • (数据大屏)(Hadoop)基于SSM框架的学院校友管理系统的设计与实现+文档
  • (一)Thymeleaf用法——Thymeleaf简介