Java---线程讲解(二)

文章目录

    • 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.mfbz.cn/a/228208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vmware安装centos7总结

vmware安装centos7总结 文章目录 vmware安装centos7总结一、配置网络&#xff08;桥接模式&#xff09;二、配置yum源&#xff08;连网配置&#xff09;三、可视化界面四、安装Docker五、安装DockerUI 一、配置网络&#xff08;桥接模式&#xff09; 网络连接模式选择桥接模式…

打包 抖音直播云游戏

抖音直播云游戏 oaid资源中的bcpkix-jdk15to18-1.68.jar与抖音云游戏的资源冲突。 其实资源名称是一样的&#xff0c;拷贝时资源名称有变化。 为解决此问题&#xff0c;需要规范化文件的资源名称&#xff0c;将.置为_ Error: Command failed: cmd /c echo off && Chc…

Java实现Socket聊天室

一、网络编程是什么&#xff1f; 在网络通信协议下&#xff0c;不同计算机上运行的程序&#xff0c;进行数据传输。 应用场景&#xff1a;即时通讯、网游对战、金融证券、国际贸易、邮件、等等。 不管是什么场景&#xff0c;都是计算机与计算机之间通过网络进行数据传输。 …

Docker网络原理及Cgroup硬件资源占用控制

docker的网络模式 获取容器的进程号 docker inspect -f {{.State.Pid}} 容器id/容器名 docker初始状态下有三种默认的网络模式 &#xff0c;bridg&#xff08;桥接&#xff09;&#xff0c;host&#xff08;主机&#xff09;&#xff0c;none&#xff08;无网络设置&#xff…

Linux C语言 39-进程间通信IPC之管道

Linux C语言 39-进程间通信IPC之管道 本节关键字&#xff1a;C语言 进程间通信 管道 FIFO 相关库函数&#xff1a;pipe、mkfifo、mknod、write、read 什么是管道&#xff1f; 管道通常指“无名管道”&#xff0c;是Unix系统中最古老的IPC通信方式。 管道的分类 管道&#…

L1-027:出租

题目描述 下面是新浪微博上曾经很火的一张图&#xff1a; 一时间网上一片求救声&#xff0c;急问这个怎么破。其实这段代码很简单&#xff0c;index数组就是arr数组的下标&#xff0c;index[0]2 对应 arr[2]1&#xff0c;index[1]0 对应 arr[0]8&#xff0c;index[2]3 对应 arr…

绝地求生:【PC】12月网页活动和特殊空投

亲爱的玩家朋友们&#xff0c;大家好&#xff01; 将为2023年画上圆满句号的大型活动和丰厚奖励已经准备就绪。参与活动即可获得武器皮肤&#xff0c;服装&#xff0c;喷漆&#xff0c;黑货票券在内的奖品&#xff0c;赶快来参与活动获得奖励吧&#xff01; 荣都上线纪念活动 …

JavaSE基础50题:19. 递归求斐波那契数列的第N项。

概述 用递归求斐波那契数列的第N项。 斐波那契数列&#xff1a; 1 1 2 3 5 8 …… f(n) f(n-1) f(n-2) 代码 public class P19 {public static int fibnacio(int n) {if (n 1 || n 2) {return 1;}int tmp fibnacio(n-1) fibnacio(n-2);return tmp;}public static void…

LLM之Agent(三):HuggingGPT根据用户需求自动调用Huggingface合适的模型

​ 浙大和微软亚洲研究院开源的HuggingGPT&#xff0c;又名JARVIS&#xff0c;它可以根据用户的自然语言描述的需求就可以自动分析需要哪些AI模型&#xff0c;然后去Huggingface上直接调用对应的模型&#xff0c;最终给出用户的解决方案。 一、HuggingGPT的工作流程 它的…

六个自媒体写作方法,提升自媒体创作收益

在自媒体时代&#xff0c;写作成为了一个不可或缺的技能。特别是对于新手来说&#xff0c;掌握一些有效的写作方法&#xff0c;可以事半功倍&#xff0c;更好地展现个人创意和观点。在这里&#xff0c;我将分享六个适合新手的自媒体写作方法&#xff0c;希望能够为你在写作之路…

外汇天眼:什么时段做外汇交易最好,有所谓的“最佳时间点”吗?

在外汇交易的时候&#xff0c;很多手动交易的投资者不知道到底什么时间段操作交易最适合自己。 我们在进行选择最佳交易时间的时候&#xff0c;一定要明白各时间段的全球各个市场的交易状况&#xff0c;这样你才能分配好自己的时间。 当然在通过技术分析与基本分析选择好币种后…

刚刚,深兰科技在国际顶级会议EMNLP竞赛中再夺两冠

12月6日至10日&#xff0c;自然语言处理领域的国际顶级会议EMNLP(自然语言处理中的经验方法会议)在新加坡召开&#xff0c;研究人员、学者和业界专业人士齐聚一堂&#xff0c;展示和讨论该领域的最新研究成果、进展和创新。 会上公布了各项任务竞赛的获奖名单&#xff0c;深兰科…

十分钟带你搞懂Python那啥

Python爬虫的用处就不需要我多说了吧&#xff0c;今天就来带大家十分钟快速学会Python是如何爬取网页信息的&#xff0c;当然大家在爬取目标网页内容之前一定要遵守该网页的爬虫规则&#xff0c;以免带来不必要的麻烦&#xff0c;因而本次的示例所爬取的网页也是自己的本地网站…

【Vulnhub 靶场】【Funbox: GaoKao】【简单】【20210606】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/funbox-gaokao,707/ 靶场下载&#xff1a;https://download.vulnhub.com/funbox/FunboxGaoKao.ova 靶场难度&#xff1a;简单 发布日期&#xff1a;2021年06月06日 文件大小&#xff1a;1.3 GB 靶场作者&#…

专业130+总分400+云南大学通信847专业基础综考研经验(原专业课827)

今年专业130总分400云南大学通信上岸&#xff0c;整体考研感觉还是比较满意&#xff0c;期间也付出了很多心血&#xff0c;走过弯路&#xff0c;下面分享一下这一年考研得失&#xff0c;希望大家可以从中有所借鉴。 先说明我在考研报名前更换成云南大学的理由&#xff1a;&…

通过项目管理软件监管新员工入职流程的方法与策略

项目管理软件是什么&#xff1f;项目管理软件都能做什么&#xff1f;是不是只有项目团队需要啊&#xff1f;NO&#xff01;项目管理软件乍听其名不免让人觉得这不过是个项目领域的专用工具。 那什么是项目呢&#xff1f;项目是为创造独特的产品、服务或成果而进行的体系化的工…

Qt内存管理、UI编辑器、客制化组件、弹出对话框、常用部件类

头文件的小技巧 #include <QtWidgets> // 在自动生成的 .h 里面加上此句 适用条件&#xff1a; QT 的内存管理 当父窗体被关闭时&#xff0c;子部件的内存会自动释放。 对象树是一种管理对象生命周期的机制。当一个对象被添加到另一个对象的子对象列表中时&#xff0…

机器学习应用 | 使用 MATLAB 进行异常检测(下)

在使用MATLAB 进行异常检测&#xff08;上&#xff09;中&#xff0c;我们探讨了什么是异常值&#xff0c;简单的一维数据异常检测问题&#xff0c;针对高维数据的有监督异常检测方法。 在&#xff08;下&#xff09;篇中&#xff0c;我们将和大家一起探讨无监督异常检测。 没…

“身份证信息批量核验:高效解决管理难题,轻松提升工作效率“

尊敬的读者们&#xff0c;您是否曾经因为身份证信息的核验而感到烦恼&#xff1f;是否曾经因为手动核验而感到繁琐和耗时&#xff1f;现在&#xff0c;我们向您介绍一款全新的工具——身份证信息批量核验器&#xff0c;它将帮助您一键解决管理难题&#xff0c;让工作事半功倍&a…

netty源码:(9)ChannelId

ChannelId代表了一个Channel的全局标识符。它提供了asShortText和asLongText两个方法来返回对应的字符串
最新文章