Java---线程讲解(二)

news2024/11/26 9:44:45

文章目录

    • 1. Runnable接口
    • 2. 卖票案例
    • 3. 同步代码块解决数据安全问题
    • 4. 同步方法解决数据安全问题
    • 5. 线程安全的类
    • 6. Lock锁


1. Runnable接口

 1. 创建线程的另一种方法是声明一个实现Runnable接口的类,之后重写run()方法,然后可以分配类的实例,在创建Thread时作为参数传递,最后启动。

 2. 具体实现Runnable接口:(1) 定义一个MyRunnable实现Runnable接口。 (2) 在MyRunnable中重写run()方法。 (3) 创建MyRunnable类对象。 (4) 创建Thread类的对象,把MyRunnable对象作为构造方法的参数。 (5) 启动线程。

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

public class MyRunnableDemo {
    public static void main(String[] args) {
        //创建MyRunnable类对象
        MyRunnable my=new MyRunnable();

        //创建Thread类对象,把MyRunnable对象作为参数传进来
        //Thread(Runnable target)
        //Thread t1=new Thread(my);
        //Thread t2=new Thread(my);

        //Thread(Runnable target, String name)
        Thread t1=new Thread(my,"线程1");
        Thread t2=new Thread(my,"线程2");

        //启动线程
        t1.start();
        t2.start();
    }
}

在这里插入图片描述
 3. 多线程的实现方案有两种:(1) 继承Thread类。 (2) 实现Runnable接口。

  • 实现Runnable接口好处:避免了Java单继承的局限性;适合多个相同程序的代码去处理同一资源的情况,把线程和程序的代码、数据有效分离,较好地体现了面向对象的设计思想。

2. 卖票案例

 1. 需求和思路:

在这里插入图片描述

 2. 代码块:

public class SellTicket implements Runnable{
    //表示有100张票
    private int tickets=100;
    @Override
    public void run() {
        while (true){
            if(tickets>0){
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

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

在这里插入图片描述
 3. 问题分析:看上面结果相同的票会出现三次,为什么呢?请参照下图理解,虽然加上了休眠时间,但是原理是一样的,都是线程抢占CPU执行权导致的。

在这里插入图片描述

3. 同步代码块解决数据安全问题

 1. 如何解决多线程安全问题:(1) 把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。 (2) Java提供了同步代码块的方式来解决。

 2. 同步代码块格式:

在这里插入图片描述

 3. 代码块举例:

public class SellTicket implements Runnable{
    //表示有100张票
    private int tickets=100;
    private Object obj= new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj) {
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                    tickets--;
                }
            }
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

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

在这里插入图片描述

 4. 同步的好处和弊端:(1) 好处:解决了多线程的数据安全问题。 (2) 弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

4. 同步方法解决数据安全问题

 1. 同步方法:就是把synchronized关键字加到方法上。

 2. 格式:修饰符 synchronized 返回值类型 方法名(方法参数){ }

 3. 同步方法的锁对象:this

 4. 代码块举例:

public class SellTicket implements Runnable{
    //表示有100张票
    private int tickets=100;
    private Object obj= new Object();
    private int x=0;

    @Override
    public void run() {
        while (true){
            if(x%2==0) {  //这里得是this,否则会出问题
                synchronized (this) {
                    if (tickets > 0) {
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--;
                    }
                }
            }else{
                sellticket();
            }
            x++;
        }
    }

    private synchronized void sellticket(){
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
            tickets--;
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

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

5. 线程安全的类

在这里插入图片描述

6. Lock锁

 1. 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

 2. Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作。

 3. Lock中获得锁和释放锁的方法:void lock():获得锁。void unlock():释放锁。

 4. Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化。

 5. 代码块举例:

public class SellTicket implements Runnable{
    //表示有100张票
    private int tickets=100;
    private Lock lock=new ReentrantLock();


    @Override
    public void run(){
        while (true) {
            lock.lock();
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                tickets--;
            }
            lock.unlock();
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1292036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构与算法编程题50

假设不带权有向图采用邻接矩阵G存储&#xff0c;设计实现以下功能的算法。 &#xff08;1&#xff09;求出图中每个顶点的出度。 &#xff08;2&#xff09;求出图中出度为0的顶点数。 &#xff08;3&#xff09;求出图中每个顶点的入度。 //参考博客&#xff1a;https://blog.…

数据库数据恢复—sqlserver数据库文件被加密,文件名被篡改的数据恢复案例

SQLServer数据库故障&#xff1a; 某公司服务器上的SQLServer数据库被加密&#xff0c;无法使用。被加密的数据库有2个&#xff0c;数据库的MDF、LDF、log文件名字被篡改。 数据库被加密截图&#xff1a; 数据库备份被加密&#xff0c;文件名字被篡改&#xff1a; SQLServer数…

Navicat 连接 GaussDB分布式的快速入门

Navicat Premium&#xff08;16.3.3 Windows版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构…

STM32CubeMx+MATLAB Simulink串口输出实验

STM32CubeMxMATLAB Simulink串口输出实验 &#x1f4cc;《STM32CubeMxMATLAB Simulink点灯程序》&#x1f4cd;相关篇《MATLAB Simulink STM32硬件在环 &#xff08;HIL&#xff09;实现例程测试》&#x1f516;需要的软件支持包&#xff1a;Embedded Coder Support Package fo…

【Java 基础】21 多线程同步与锁

文章目录 1.存在的问题2.使用同步解决问题1) synchronized2) volatile3) 锁 总结 用多线程过程中&#xff0c;有可能出现 多个线程同时处理&#xff08;获取或修改等&#xff09;同一个数据&#xff0c;这个时候就 会发生数据不同步的问题&#xff0c; 因此出现了同步和锁来…

html和css写淘宝的快速导航条

目录 1、css代码 2、html代码 1、css代码 <style>* {margin: 0;padding: 0;list-style: none;text-decoration: none;}.nav {width: 900px;height: 40px;background-color: rgb(247, 249, 250);margin: 50px auto;padding-left: 30px;}.nav>li {float: left;width: 1…

软件测试中年危机?30岁大关?“我“该如何破局...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 在软件测试行业摸…

Oracle 表数据锁了,处理方式,Oracle锁表处理

Oracle 表数据锁了&#xff0c;处理方式&#xff0c;Oracle锁表处理 参考连接&#xff1a; Oracle锁表处理_oracle锁表怎么解决_辣椒炒鸡的博客-CSDN博客 实践&#xff1a; 1、查看被锁的表 select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object …

QTimer的使用

参考&#xff1a; Qt 定时器 (QTimer)的几种使用方法-CSDN博客 QTimer 如何判断QT定时器在工作&#xff1f;-CSDN博客 (1)timeout信号 每隔5秒&#xff0c;timer发射timeout()信号&#xff0c;w执行onTimeout()槽函数。 Widget w;QTimer timer;timer.start(5*1000);QObjec…

点评项目——商户查询缓存

2023.12.7 redis实现商户查询缓存 在企业开发中&#xff0c;用户的访问量动辄成百上千万&#xff0c;如果没有缓存机制&#xff0c;数据库将承受很大的压力。本章我们使用redis来实现商户查询缓存。 原来的操作是根据商铺id直接从数据库查询商铺信息&#xff0c;为了防止频繁地…

WIFI7:O7851PM吞吐测试

近年来&#xff0c;随着科技的飞速发展&#xff0c;WIFI技术也在不断演进&#xff0c;从WIFI6逐渐过渡到WIFI6E&#xff0c;再到如今备受关注的WIFI7。这次我们将聚焦于我们欧飞信最新研发的WIFI7模组&#xff1a;O7851PM&#xff0c;通过对WIFI7的核心指标——吞吐量测试&…

IoT DC3 是一个基于 Spring Cloud 全开源物联网平台 linux docker部署傻瓜化步骤

如有不了解可先参考我的另一篇文章本地部署:IoT DC3 是一个基于 Spring Cloud 的开源的、分布式的物联网(IoT)平台本地部署步骤 如有不了解可先参考我的另一篇文章本地部署: 1 环境准备: JDK 8 以上 docker 安装好 下载docker-compose-dev.yml 文件 执行基础环境docker安装 …

如何使用技术 SEO 优化 Pinterest 富图钉

Pinterest 可以影响搜索引擎排名&#xff0c;尤其是谷歌。不过&#xff0c;它的作用方式与其他搜索引擎优化因素不同。这就是 Google 将图钉放在 nofollow 列表中。但是&#xff0c;它们仍然可以作为搜索引擎优化的一个重要因素。 高质量的图钉具有高分辨率的图片、吸引人的内…

【高数:1 映射与函数】

【高数&#xff1a;1 映射与函数】 例2.1 绝对值函数例2.2 符号函数例2.3 反函数表示例2.4 双曲正弦sinh&#xff0c;双曲余弦cosh&#xff0c;双曲正切tanh 参考书籍&#xff1a;毕文斌, 毛悦悦. Python漫游数学王国[M]. 北京&#xff1a;清华大学出版社&#xff0c;2022. 例2…

【Hung-Yi Lee】强化学习笔记

文章目录 What is RLPolicy GradientPolicy Gradient实际是怎么做的On-policy v.s. Off-policyExploration配音大师 Actor-Critic训练value function的方式网络设计DQN Reward ShapingNo Reward&#xff1a;Learning from Demonstration What is RL 定义一个策略网络&#xff0…

JM中ref_pic_list_modification bug记录

问题描述 今天在用JM对YUV420p编码时,发现编出的码流用ffplay播放花屏,报如下错误: JM的版本时19.1,没有使能B帧,PicOrderCntType设置为2,其它都是encoder.cfg中的默认配置。我用一些码流分析工具播放H264码流正常,用一些播放器播放也都存在花屏,不过大多数播放器都是…

Java程序员,你掌握了多线程吗?

文章目录 01 多线程对于Java的意义02 为什么Java工程师必须掌握多线程03 Java多线程使用方式04 如何学好Java多线程写作末尾 摘要&#xff1a;互联网的每一个角落&#xff0c;无论是大型电商平台的秒杀活动&#xff0c;社交平台的实时消息推送&#xff0c;还是在线视频平台的流…

word中如何插入公式,如何高效使用mathtype,遇到他人论文的复杂公式如何直接粘贴复制,为你一一答疑解惑!!

文章目录 一、论文中插入公式---最原始&#xff0c;最好用&#xff0c;最稳定的方法1.1 主页--插入---对象1.2 找到公式编辑器&#xff0c;对应你的版本1.3 直接输入公式&#xff0c;关闭界面 二、如何做好一个懒人——如何直接粘贴别人PDF等格式论文中的公式&#xff1f;2.1 使…

活动回顾|德州仪器嵌入式技术创新发展研讨会(上海站)成功举办,信驰达科技携手TI推动技术创新

2023年11月28日&#xff0c;德州仪器(TI)嵌入式技术创新发展研讨会在上海顺利举办。作为TI中国第三方IDH&#xff0c;深圳市信驰达科技有限公司受邀参加&#xff0c;并设置展位&#xff0c;展出CC2340系列低功耗蓝牙模块及TPMS、蓝牙数字钥匙解决方案&#xff0c;与众多业内伙伴…

种下一棵栀子花

女孩说自己是男孩当年伸手就可触及的栀子花.男孩沉默了,明白了当初失去了什么. 时光倒流,13年前的一个夏天夜晚,男孩与女孩同在沪城,女孩分享了自己的照片给男孩.男孩站在窗前,那晚的夜空很美丽,仿佛托着那个白衣裳女孩的纯真的梦,来到了自己的身边. 女孩说彼此间只是少了一个深…