【从入门到起飞】JavaSE—多线程(3)(生命周期,线程安全问题,同步方法)

🎊专栏【JavaSE】

🍔喜欢的诗句:路漫漫其修远兮,吾将上下而求索。

🎆音乐分享【如愿】

🎄欢迎并且感谢大家指出小吉的问题🥰

文章目录

🍔生命周期

🎄线程的安全问题

发现有两个问题,相同的票出现了多次,出现了超出范围的票

🏳️‍🌈原因

首先线程被线程一抢走了

线程一执行到了sleep,会休眠10ms,然后ticket+1,变为了1
然后线程被线程二抢走了

线程二执行到了sleep,会休眠10ms,然后ticket+1,变为了2
然后线程被线程三抢走了

线程三执行到了sleep,会休眠10ms,然后ticket+1,变为了3

现在ticket是3,就会打印3次ticket=3的结果
这就是重复票和超出范围的原因

⭐改进方法

我们把下面的代码给框起来,设置一个线程执行完这个代码块后,其他线程才能执行

🌺同步代码块

把操作共享数据的代码给锁起来

java 复制代码
synchronizd(锁){
	操作共享数据的代码
}
  • 锁默认打开,有一个线程进去了,锁自动关闭
  • 里面的代码全部执行完毕,线程出来,锁自动打开

我们把之前的代码块用锁包围起来康康效果如何

运行成功

MyThread.java

java 复制代码
public class MyThread extends Thread {

    //表示这个类的所有对象,都共享ticket数据
    static int ticket = 0;//0~99

    //锁的对象,一定要是唯一的
    static Object obj=new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (ticket < 100) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket++;
                    System.out.println(getName() + "正在卖第" + ticket + "张票");
                } else {
                    break;
                }
            }
        }
    }
}

Demo1.java

java 复制代码
package IODemo6;

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        //创建线程对象
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        MyThread t3=new MyThread();

        //起名字
        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

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

⭐细节

  1. 锁必须要写到循环里面
  2. 锁对象必须唯一

🌺同步方法

就是把synchronized关键字加到方法上

java 复制代码
修饰符 synchronized 返回值类型 方法名(方法参数){
	......
}

MyRunnable.java

java 复制代码
public class MyRunnable implements Runnable{
    int ticket=0;

    @Override
    public void run() {
        while (true){
            //同步方法
            if (method()) break;
        }
    }

    public synchronized boolean method(){
        //共享数据 到了末尾
        if (ticket==100){
            return true;
        }else {
            //共享数据 没有到末尾
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket++;
            System.out.println(Thread.currentThread().getName()+"在卖第"+ticket+"张票!!!");
        }
        return false;
    }
}

ThreadDemo.java

java 复制代码
public class ThreadDemo {
    public static void main(String[] args) {
        MyRunnable mr=new MyRunnable();

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

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

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

如果大家有不明白的知识点,欢迎在评论区进行讨论

相关推荐
坐吃山猪2 分钟前
Electron04-系统通知小闹钟
开发语言·javascript·ecmascript
翔云 OCR API3 分钟前
护照NFC识读鉴伪接口集成-让身份核验更加智能与高效
开发语言·人工智能·python·计算机视觉·ocr
程序喵大人11 分钟前
CMake入门教程
开发语言·c++·cmake·cmake入门
老华带你飞16 分钟前
房屋租赁管理|基于springboot + vue房屋租赁管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·毕设
半生过往28 分钟前
前端运行PHP 快速上手 使用 PHPStudy Pro 详细搭建与使用指南
开发语言·前端·php
zlpzlpzyd30 分钟前
ecmascript中Promise和async/await的区别
开发语言·前端·ecmascript
凛_Lin~~37 分钟前
安卓 Java线程八股文 (线程、多线程、线程池、线程安全)
android·java·开发语言
C语言不精41 分钟前
c语言-优雅的多级菜单设计与实现
c语言·开发语言·算法
geekmice41 分钟前
thymeleaf处理参数传递问题
开发语言·lua
哈哈哈笑什么42 分钟前
企业级CompletableFuture并行化完整方案,接口从10s到100ms
java·后端·spring cloud