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

专栏【JavaSE】
喜欢的诗句:路漫漫其修远兮,吾将上下而求索。
音乐分享【如愿】
欢迎并且感谢大家指出小吉的问题

文章目录

  • 生命周期
  • 线程的安全问题
    • ️‍原因
    • ⭐改进方法
  • 同步代码块
    • ⭐细节
  • 同步方法

生命周期

【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第1张图片

线程的安全问题

【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第2张图片
发现有两个问题,相同的票出现了多次,出现了超出范围的票

️‍原因

首先线程被线程一抢走了
线程一执行到了sleep,会休眠10ms,然后ticket+1,变为了1
然后线程被线程二抢走了
线程二执行到了sleep,会休眠10ms,然后ticket+1,变为了2
然后线程被线程三抢走了
线程三执行到了sleep,会休眠10ms,然后ticket+1,变为了3
现在ticket是3,就会打印3次ticket=3的结果
这就是重复票和超出范围的原因
【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第3张图片

⭐改进方法

我们把下面的代码给框起来,设置一个线程执行完这个代码块后,其他线程才能执行
【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第4张图片

同步代码块

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

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

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

【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第5张图片

运行成功

MyThread.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

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关键字加到方法上

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

【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第6张图片
MyRunnable.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

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();
    }
}

【从入门到起飞】JavaSE—多线程(2)(生命周期,线程安全问题,同步方法)_第7张图片

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

你可能感兴趣的:(Java基础,java,开发语言)