Java筑基30-线程02-生命周期&同步方法

目录

一、线程生命周期

1.线程六大状态

2.线程状态转换图

二、线程同步

1.同步介绍

2.同步方法

3.案例(模拟三个线程同时售票)

4.同步原理

5.同步注意事项

三、线程死锁

四、释放锁

1.会释放锁

2.不会释放锁

五、线程练习题

1.线程调用练习

2.线程同步练习


一、线程生命周期

1.线程六大状态

JDK中用线程的枚举表示了线程的集中状态。

  • public static enum Thread.State extends Enum<Thread.State>线程状态。线程可以处于以下状态之一:一个线程可以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
    • NEW尚未启动的线程处于此状态。
    • RUNNABLE在Java虚拟机中执行的线程处于此状态。
    • BLOCKED被阻塞等待监视器锁定的线程处于此状态。
    • WAITING正在等待另一个线程执行特定动作的线程处于此状态。
    • TIMED_WAITING正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
    • TERMINATED已退出的线程处于此状态。

一个线程可以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。

2.线程状态转换图

/**
 * @author: 程序员飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class ThreadState_ {
    public static void main(String[] args) throws InterruptedException {
        T0 t0 = new T0();
        System.out.println(t0.getName() + "状态:" + t0.getState());
        t0.start();
        while(Thread.State.TERMINATED != t0.getState()){
            System.out.println(t0.getName() + "状态:" + t0.getState());
            Thread.sleep(1000);
        }
        System.out.println(t0.getName() + "状态:" + t0.getState());
    }
}

class T0 extends Thread{
    @Override
    public void run() {
        while(true){
            for (int i = 1; i <= 5; i++) {
                System.out.println("hi" + i + "状态:" + Thread.currentThread().getState());

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            break;
        }
    }
}

输出:

Thread-0状态:NEW

Thread-0状态:RUNNABLE

hi1状态:RUNNABLE

Thread-0状态:RUNNABLE

hi2状态:RUNNABLE

Thread-0状态:RUNNABLE

hi3状态:RUNNABLE

Thread-0状态:RUNNABLE

hi4状态:RUNNABLE

Thread-0状态:RUNNABLE

hi5状态:RUNNABLE

Thread-0状态:RUNNABLE

Thread-0状态:TERMINATED

二、线程同步

1.同步介绍

2.同步方法

3.案例(模拟三个线程同时售票)

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class SellTicket {
    public static void main(String[] args) {
        Sell sell = new Sell();
        new Thread(sell).start();
        new Thread(sell).start();
        new Thread(sell).start();
    }

}

class Sell implements Runnable{
    static int ticket = 10;
    private boolean loop = true;
    public synchronized void m(){
        if(ticket <= 0){
            setLoop(false);
            System.out.println("没票了,售票结束");
            return;
        }
        try {
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("窗口" + Thread.currentThread().getName()+"卖出了一张票,剩余" + (--ticket) );
    }

    @Override
    public void run() {
        while(loop){
            m();
        }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }
}

输出:

窗口Thread-0卖出了一张票,剩余9

窗口Thread-0卖出了一张票,剩余8

窗口Thread-0卖出了一张票,剩余7

窗口Thread-0卖出了一张票,剩余6

窗口Thread-0卖出了一张票,剩余5

窗口Thread-0卖出了一张票,剩余4

窗口Thread-0卖出了一张票,剩余3

窗口Thread-0卖出了一张票,剩余2

窗口Thread-0卖出了一张票,剩余1

窗口Thread-0卖出了一张票,剩余0

没票了,售票结束

没票了,售票结束

没票了,售票结束

4.同步原理

5.同步注意事项

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class SellTicket {
    public static void main(String[] args) {
        Sell sell = new Sell();
        new Thread(sell).start();
        new Thread(sell).start();
        new Thread(sell).start();
    }
}

class Sell implements Runnable{
    Object object = new Object();
    static int ticket = 10;
    private boolean loop = true;

    //同步方法(静态的)的锁为当前类本身
    public synchronized static void m1(){//此时锁是加在Sell.class

    }

    public static void m2(){//在静态方法中实现同步代码快,类名.class
        synchronized (Sell.class){
            System.out.println("lalalala");
        }
    }

    public /*synchronized*/ void m(){//同步方法
        synchronized (/*this*/ object){//同步锁代码块,此时this指当前对象,锁object也可以,因为是操作的同一个对象
            if(ticket <= 0){
                setLoop(false);
                System.out.println("没票了,售票结束");
                return;
            }
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("窗口" + Thread.currentThread().getName()+"卖出了一张票,剩余" + (--ticket) );
        }
    }

    @Override
    public void run() {
        while(loop){
            m();
        }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }
}

三、线程死锁

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class DeadLock_ {
    public static void main(String[] args) {
        DeadLockDemo deadLockDemo1 = new DeadLockDemo(true);
        DeadLockDemo deadLockDemo2 = new DeadLockDemo(false);
        deadLockDemo1.start();
        deadLockDemo2.start();
    }
}

class DeadLockDemo extends Thread{
    static Object o1 = new Object();
    static Object o2 = new Object();
    boolean flag;

    public DeadLockDemo(boolean flag){
        this.flag = flag;
    }

    public void run(){
        if(flag){
            synchronized (o1){
                System.out.println(Thread.currentThread().getName() + "进入1");
                synchronized (o2){
                    System.out.println(Thread.currentThread().getName() + "进入2");
                }
            }
        }else{
            synchronized (o2){
                System.out.println(Thread.currentThread().getName() + "进入3");
                synchronized (o1){
                    System.out.println(Thread.currentThread().getName() + "进入4");
                }
            }
        }
    }
}

运行结果:

四、释放锁

1.会释放锁

2.不会释放锁

d91663ba1ba58fa5b79577dbe02ab0fc.png

五、线程练习题

1.线程调用练习

import java.util.Scanner;

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class HomeWork01 {
    public static void main(String[] args) {
        A a = new A();
        B b = new B(a);
        a.start();
        b.start();
    }


}

class A extends Thread{
    private boolean loop = true;

    public void setLoop(boolean loop) {
        this.loop = loop;
    }

    int count;
    @Override
    public void run() {
        while(loop){
            ++count;
            System.out.print((int)((Math.random()*100 + 1))+ " ");//随机打印1~100之间的整数
            if(count%10 == 0){
                System.out.println();//每打印10个数换行
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class B extends Thread{
    private A a;
    private Scanner scanner = new Scanner(System.in);

    public B(A a) {
        this.a = a;
    }

    @Override
    public void run() {
        while(true){
            System.out.println("输入指令'Q'表示退出:");
            char c = scanner.next().toUpperCase().charAt(0);//接收控制台输入的字符'q'或'Q'
            if(c == 'Q'){
                a.setLoop(false);//将变量置为false,通知线程A退出
                break;
            }
        }

    }
}

输出:

输入指令'Q'表示退出:

80 79 77 25 58 63 97 47 39 99

2 34 44 73 79 87 98 q

Process finished with exit code 0

2.线程同步练习

/**
 * @author:程序员飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class HomeWork02 {
    public static void main(String[] args) {
        DrawMoney drawMoney = new DrawMoney();
        Thread thread1 = new Thread(drawMoney);
        thread1.setName("t1");
        Thread thread2 = new Thread(drawMoney);
        thread2.setName("t2");
        thread1.start();
        thread2.start();
    }
}

class DrawMoney implements Runnable{
    private int money = 5000;
    @Override
    public void run() {
        System.out.println("当前一共有" + money);
        while(true){
            /**
             * 1. 使用synchronized实现线程同步
             * 2. 当多个线程执行到此处,就会去争夺this对象锁
             * 3. 哪个线程获取到this对象锁,就执行synchronized代码块,执行完成后,会释放this对象锁
             * 4.争夺不到this对象锁,就blocked,准备继续争夺
             * 5. this对象锁是非公平锁
             */
            synchronized (this){
                if(money < 1000){
                    System.out.println("余额不足");
                    break;
                }
                money -= 1000;
                System.out.println(Thread.currentThread().getName() + "取了1000元,当前余额" + money);
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

输出:

当前一共有5000

当前一共有5000

t1取了1000元,当前余额4000

t2取了1000元,当前余额3000

t2取了1000元,当前余额2000

t1取了1000元,当前余额1000

t1取了1000元,当前余额0

余额不足

余额不足

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员飞扬

赠人玫瑰,手有余香,感谢支持!

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

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

打赏作者

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

抵扣说明:

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

余额充值