【Day22】解决线程安全问题以及JDK1.5新增

Java SimpleDateFormat线程安全与DateTimeFormatter迁移指南 SimpleDateFormat是Java中广泛使用的日期格式化工具,但其内部可变状态导致天然不支持多线程并发——这是理解Java时间API演进的关键起点。其核心问题源于非线程安全(thread-safe)设计与宽松解析机制,易引发时序竞争、数据错乱和隐式时区偏移。现代解决方案依托java.time包的不可变性(immutability)与领域模型,如DateTimeFormatter通过无状态设计彻底规避并发风险,并提供更精准的语义表达(如LocalDateTime、Instant)。该方案已成微服务、高 阅读详情

 

目录

 总体框架:

同步方法改进:

使用同步机制将单例模式中的懒汉式更改为线程安全的

 解决线程问题的方式三:Lock锁-----JDK5.0新增

方式三修改


总体框架:

/**
 *    题目:三个窗口售票,总票数100张,售完为止
 *
 * 出现线程安全解决方式:
 * 方式一:
 * 1、同步代码块;
 *  synchronized(同步代码块){
 *      //需要被同步的代码
 *  }
 *  说明:1、操作共享数据的代码,即为需要被同步的代码
 *       2、共享数据:多个线程共同操作的变量,比如:ticket就是共享数据。
 *       3、同步监视器,俗称:锁。任何一个类都可以充当一把锁。
 *          要求:多个线程必须用同意把锁
 *
 * 2、this
 *  synchronized(this){  //this表示当前对象,且当前对象只有一个
 *
 *  }
 * 3、当前类.class充当,类只会加载一次
 *  synchronized(当前类.class){
 *
 *  }
 *
 *  方式二:同步方法
 *  如果操作共享数据的代码完整的声明在一个方法中国,我们不妨将此方法声明同步的
 *  同步代码块总结:
 * 1、同步方法仍涉及到同步监控器,只是不愿要我们显示声明
 * 2、非静态的同步方式,同步监控器是:this
 *      静态的同步方式,同步监控器是当前类本身
 *
 *
 *使用同步机制将单例模式中的懒汉式更改为线程安全的
 *
 *
 * 解决线程问题的方式三:Lock锁-----JDK5.0新增
 * 1、实例化lock
 * 2、调用锁定方法lock()
 * 3、调用解锁方法:unlock()
 */
 /*
 * 出现线程安全解决方式:
 * 方式一:
 * 1、同步代码块;
 *  synchronized(同步代码块){
 *      //需要被同步的代码
 *  }
 */


class window1 implements Runnable{
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while(true){
//            这里也可以使用this,需要把obj的创建对象删除,在把synchronized()括号里替换成this
            synchronized(obj) {
                if (ticket > 0) {
//                出现线程安全
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class Test1 {
    public static void main(String[] args) {

        window1 wd = new window1();
        Thread t1=new Thread(wd);
        Thread t2=new Thread(wd);
        Thread t3=new Thread(wd);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

        t1.start();
        t2.start();
        t3.start();
    }
}
/**
 * 方式二:
 * 使用同步方法解决实现Runnable接口的线程安全问题
 * 代码的执行放在另一个方法中,声明的方式的返回值是synchronized
 *
*/
class window2 implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        while(true){
            show();

        }

    }
    private synchronized void show(){ 
//        或者使用同步代码块:synchronized (this) {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
                ticket--;
            }
    }
}
public class Test2 {
    public static void main(String[] args) {

        window2 wd = new window2();
        Thread t1=new Thread(wd);
        Thread t2=new Thread(wd);
        Thread t3=new Thread(wd);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

        t1.start();
        t2.start();
        t3.start();
    }
}

同步方法改进:

使用同步机制将单例模式中的懒汉式更改为线程安全的

class Bank {
    private Bank() {
    }

    private static Bank instance = null;

    public static Bank getInstance() {

//        方式一:效率差
//        synchronized (Bank.class) {
//            if (instance == null) {
//                instance = new Bank();
//            }
//            return instance;
//        }


//        方式二:效率高一点
        if (instance == null) {
            //Bank.class:是代表当前类
            synchronized (Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }
                return instance;
            }
        }
        return null;
    }
}

 解决线程问题的方式三:Lock锁-----JDK5.0新增

class Window4 implements Runnable{
    private int ticket =100;

//    1、实例化lock
    private ReentrantLock lock=new ReentrantLock(true);
    @Override
    public void run() {
        while(true){
            try {
//                2、调用锁定方法lock();
                lock.lock();

                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "销售为:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }finally {
//                3、调用解锁方法:unlock()
                lock.unlock();
            }
        }
    }
}

public class Test5 {

    public static void main(String[] args) {
        Window4 window=new Window4();

        Thread t1=new Thread(window);
        Thread t2=new Thread(window);
        Thread t3=new Thread(window);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

        t1.start();
        t2.start();
        t3.start();



    }
}

方式三修改

**
 * 创建线程的方式三:实现collable接口的方式。----JDK 5.0新增
 * callable接口的方式创建多线程比Runnable接口创建多线程方式强大?
 * 1、call()可以有返回值
 * 2、call()可以抛出异常,被外面的操作捕获,获取异常的信息
 * 3、callable是支持泛型的
 * Description:
 * @author: ----千里之行,始于足下----
 * date: 2022/8/15  15:12
*/
//1、创建一个实现callable的实现类
class NumThread implements Callable{
    //2、实现call方法,将此线程需要执行的操作声明在call()中
    @Override
    public Object call() throws Exception {
        int sum=0;
        for (int i = 1; i <= 100; i++) {
            if(i%2==0){
                System.out.println(i);
                sum+=i;
            }
        }
        return sum;
    }
}
public class ThreadNew {
    public static void main(String[] args) {
        //3、创建callable接口实现类的对象
        NumThread numThread =new NumThread();
        //4、将此callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
        FutureTask futureTask =new FutureTask(numThread);
        //5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        new Thread(futureTask).start();

        try {
//            6、获取callable中call方法的返回值
//            get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
            Object sum = futureTask.get();
            System.out.println(sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }


    }
}

JDK 1.8(Java 8)新特性详解 Java 8(JDK 1.8)是Java发展史上的重要里程碑版本,发布于2014年3月。该版本引入了一系列革命性特性,主要包括:Lambda表达式和函数式接口支持函数式编程;方法引用简化代码;Stream API提供强大的流式数据处理能力;Optional类优雅处理空值;接口支持默认和静态方法;全新的java.time日期时间API;CompletableFuture改进异步编程;集合框架增强(如HashMap红黑树优化);新增Base64支持、Nashorn JavaScript引擎等。这些特性不仅提升了 阅读详情

相关推荐

HFSS的边界条件与激励方式

在电磁场理论学习中我们知道,电磁场问题的求解都归结于麦克斯韦(Maxwell)方程组的求解,在HFSS中波动方程的求解同样是由微分形式的麦克斯韦方程推导出来的。而边界条件定义了求解区域的边界以及不同物体交界处的电磁场特性,是求解麦克斯韦方程的基础。 只有在假定场矢量是单值、有界、并且沿空间连续分布的前提下,微分形式的麦克斯韦方程组才是有效的;而在求解区域的边界,不同介质的交界处和场源处,场矢量是不连续的,那么场的导数也就失去了意义。 边界条件就是定义跨越不连续边界处的电磁场特性,因此,正确地理解、定义并

ASH_GUARDIAN的博客 1万+

java 源码阅读(四)Vector

java 源码阅读(四)Vector Vector是一种变长集合类,基于数组实现。ArrayList允许空值和重复元素。当往Vector中添加的元素数量超过底层数量时,会进行扩容。Vector实现了RandomAccess接口,所以可以保证在O(1)复杂度下完成随机查找操作。是一个线程安全类。 继承/实现 构造函数 protected Object[] elementData; protecte...

regrethh的博客 260

STM32G0实战:手把手教你用国产GD25Q16 Flash存储传感器数据(附完整驱动)

本文详细介绍了如何使用国产GD25Q16 Flash芯片与STM32G0系列MCU实现传感器数据存储的完整方案。从SPI接口配置、驱动层实现到存储系统架构设计,提供了实战代码和优化策略,帮助开发者快速构建高性价比的物联网数据存储系统。

weixin_30733003的博客 107

JDK1.8新增的日期与时间API

JDK1.8新增的日期与时间API用法

weixin_43895371的博客 868

sap销售发货的流程_SAP销售订单发货后如何实现发票的自动创建?

问SAP销售订单发货后如何实现发票的自动创建?答业务场景有些快消零售企业,SAP系统单据量大,单据金额少,一般在销售发货后即可确认收入。此时无需人工在系统内操作VF01或者VF04进行开票操作,可将该操作设置成后台作业进行自动批量开票,具体操作如下:1、定义任务:VF06输入完以上信息,点击保存进入以下界面:说明:当前日期的意思是“开票的日期”等于“系统电脑中的当前日期”当前日期+/-...

weixin_42358409的博客 3367

微信小程序订阅消息实战:如何绕过长期订阅限制实现多次发送(附PHP代码)

本文针对微信小程序开发者无法获取长期订阅消息权限的痛点,提供了一套完整的实战解决方案。通过深入剖析一次性订阅与长期订阅的规则差异,结合巧妙的交互设计、稳健的PHP服务端发送引擎(含高并发处理与失败重试机制)以及授权池管理等高级策略,帮助开发者在合规前提下,构建高可用的消息推送系统,有效提升通知触达率与用户体验。

weixin_29008805的博客 625

JDK中的日期时间API

一、JDK1.8之前的日期时间API 获取系统当前时间System类中的currentTimeMills() 返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差 2.java.util.Date类与java.sql.Date类 1.两个构造器的使用 构造器一:Date():创建一个对应当前时间的Date对象 构造器二:创建指定毫秒数的date对象 2.两个方法的使用 >toString():显示当前的年、月、日、时、分、秒。 >getTime(): 获取当前Date对象

weixin_44585687的博客 387

从零开始:使用英伟达nx开发板部署目标检测算法的全过程

英伟达nx开发板烧录、依赖安装、开发板联网

weixin_51192760的博客 3762

《day15---多线程安全问题_JDK1.5的锁机制》

1 //15同步问题的分析案例以及解决思路 2 3 //两个客户到一个银行去存钱,每个客户一次存100,存3次。 4 //问题,该程序是否有安全问题,如果有,写出分析过程,并定于解决方案。 5 6 /* 7 发现运行结果: 8 sum=200 9 sum=200 10 sum=300 11 sum=400 12 sum=600 13 su...

108

c语言版数据结构课程设计 学生成绩管理系统

此学生成绩管理系统完成15项功能,是我经过很多次的修改得到的。花费时间不短,功能齐全,主要完成了:输入,输出,插入,修改,删除,查询,读取文件,写入文件,复制文件,建立索引,显示各种情况下的信息,追加学生信息等等功能。一共15项。   代码如下: // shujujiegou.cpp : 定义控制台应用程序的入口点。///**本程序采用数组链表形式,原因:数组查询速度快,数组也能实现动态存储

Java 1万+

实战:如何通过修改VTS和HTS调整GC4653 sensor帧率(附完整计算步骤)

本文以GC4653图像传感器为例,详细解析了通过修改VTS和HTS寄存器来精确调整输出帧率的完整流程。文章深入剖析了帧率计算公式FPS = PCLK / (VTS × HTS)的核心原理,并提供了从获取寄存器参数、计算目标VTS值到系统验证的实战步骤,帮助工程师掌握独立优化Sensor性能、提升低照度画质的关键技能。

gin88的博客 338

有没有使用JDK1.8 中的日期与时间API?

为了解决 JDK 中时间与日期较难使用的问题,JDK 1.8 开始,吸收了 Joda-Time 很多功能,新增 java.time 包,加了。25、方便时间建模、机器处理的时间处理类 Instant,起始时间 1970-01-01 00:00:00。26、Duration:LocalTime、LocalDateTime、Intant 的时间差处理。19、通过 LocalTime 创建日期时间对象。28、修改日期、时间对象,返回副本。27、日期时间,前、后、相等比较。17、获取当前日期时间对象。

6个日的博客 366

Open3D 使用RANSAC分割平面【2026最新版】

使用RANSAC从点云中分割平面,用segement_plane函数。博客长期更新,本文最新更新时间为:2026年2月28日。

点云侠的博客 37万+

JAVA重点基础、进阶知识及易错点总结(22)日期时间 API(JDK8 新版)

Java 8 日期时间 API 摘要 Java 8 引入了全新的 java.time 包,解决了旧版 Date 和 Calendar 的三大痛点:设计混乱、线程不安全、API 繁琐。新版 API 具有不可变性(线程安全)、语义清晰(日期/时间分离)、计算便捷等优势。 核心类包括: LocalDate(纯日期) LocalTime(纯时间) LocalDateTime(日期+时间) Instant(时间戳) 关键特性: 所有类都是不可变的,修改操作必须接收返回值 DateTimeFormatter 线程安全,

qq_52071206的博客 706

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day22】—— 并发编程2

百日闭关修炼,每日三道高频面试题。一起冲进大厂!今天是并发编程2,看什么看?快上车!

陈哈哈的菜园子 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

day22每日一考

1.Map存储数据的特点是什么?并指明key,value,entry存储数据的特点。2.描述HashMap的底层实现原理(jdk8版)3.Map中常用实现类有哪些?各自有什么特点?4.如何遍历Map中的key-value对,代码实现5.Collection和Collections的区别?......

m0_47711130的博客 263

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Day499&500&501&502&503&504.马士兵22春招面试题① -面经

马士兵22春招面试题① 1、Java面向对象有哪些特征? 三大特征 继承 父类方法属性复用,增强代码的复用性 多态 必备要求: 继承 重写 父类引用指向子类对象 Animal animal = new Dog(); 增加代码的可移植性 增加代码的健壮性 灵活性 封装 增加了代码的可维护性 增强代码的复用性 2、ArrayList和LinkedList的区别 相同点 都实现了List接口 不同点 前者 底层数组 访问数据更方便 后者

阿昌爱Java 4148

尚硅谷 java 学习 (b 站版)Day21、多线程

多线程的相关基础知识

qq_46648403的博客 1098

Day22 - 集合 - 1.Collection集合

Collection集合概述是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现创建Collection集合的对象多态的方式具体的实现类ArrayListCollection集合常用方法方法名说明添加元素从集合中移除指定的元素根据条件进行移除清空集合中的元素判断集合中是否存在指定的元素判断集合是否为空int size()集合的长度,也就是集合中元素的个数。

tang7mj的博客 848

05day22

常用类, StringBuffer 枚举类等

weixin_53906587的博客 60

java.sql.Date和java.util.Date的区别

Date的Api记录

6个日的博客 1675

集合框架——Day5

方法作用特点/返回值添加/修改元素key 存在会覆盖旧值,返回旧 value删除指定 key 的键值对返回被删除的 value,不存在返回 nullclear()清空集合无返回值判断是否包含某个 key返回 boolean判断是否包含某个 value返回 booleanisEmpty()判断集合是否为空返回 booleansize()返回键值对个数返回 int📌这些方法是所有 Map 实现类(HashMap、TreeMap、LinkedHashMap…)都具备的通用功能,主要负责。

2301_82143894的博客 1082

30天搞定Java--day21

30天搞定Java的第21天,内容主要包括JDK8及以前的日期时间API、Java比较器、System类、Math类、BigInteger类及BigDecimal类等

想骑单车环游世界 815

day22_多线程02【线程池-Executors-ThreadPoolExecutor-volatile-AtomicInteger-并发工具类】

线程池-Executors-ThreadPoolExecutor-volatile-AtomicInteger-并发工具类

weixin_42929213的博客 457

Java面试---Day1

Java面试—Day1 星光不问赶路人,时间不负有心人 文章目录Java面试---Day11、栈、堆、方法区区别2、Java中 == 和 equals 和 hashCode 的区别3、int、char、long 各占多少字节数4、int 和 Integer 的区别5、谈谈对Java多态的理解6、String、StringBuffer、StringBuilder的区别7、什么是内部类?内部类的作用8、抽象类和接口的区别9、抽象类的意义10、抽象类与接口的应用场景11. 接口的意义 1、栈、堆、方法区区别

乐褀的博客 538

新星计划Day 1 b站尚硅谷java常用类 479p-489p

479p 课后练习1 练习1:字符串"2020-09-08"转换为java.sql.Date public void testExer() throws ParseException{ String birth="2020-09-08"; SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd"); Date date=sdf1.parse(birth); java.sql.Date birthDate=new java.s

qq_46272491的博客 861
上一篇: 【Day21】Java线程(创建线程的两种方法)
下一篇: 【23】线程相关扩展习题
「已注销」
博客等级 码龄4年 169粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

老板大气,I am happy

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值