栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程(二)生命周期、线程安全、同步

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程(二)生命周期、线程安全、同步

目录

1.线程的生命周期

2.线程的同步

方式一:同步代码块

1.使用【同步代码块】解决【实现Runnable接口】的线程安全问题

2.使用【同步代码块】解决【继承Thread类】的线程安全问题

方式二:同步方法

3.使用【同步方法】解决【实现Runnable接口】的线程安全问题

4.使用【同步方法】解决【继承Thread类】的线程安全问题


1.线程的生命周期

        要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整生命周期中通常要经历如下的五种状态。

  1. 就绪:当一个Thread类或其子类对象被声明并创建时,新生的线程对象处于新建状态。
  2. 就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源。
  3. 运行:当就绪的线程被调用并获得CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能。
  4. 阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态。
  5. 死亡:线程完成了它的全部工作或线程被提前强制性的中止或出现异常导致结束。

  

2.线程的同步
  • 多个线程执行的不确定性引起执行结果的不稳定。
  • 多个线程对账本的共享,会造成操作的不完整性,会破坏数据。
  • 在Java中,通过同步机制,来解决线程的安全问题。

方式一:同步代码块
synchronized(同步监视器){
    //需要被同步的代码
}

说明:

        1.操作共享数据的代码,即为需要被同步的代码。

        2.共享数据:多个线程共同操作的变量。

        3.同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。要求多个线程必须要共用同一把锁。

1.使用【同步代码块】解决【实现Runnable接口】的线程安全问题
  • 在实现Runnable接口创建的多线程方式中,可以考虑使用this充当同步监视器。
class Window1 implements Runnable {
    public int ticket = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {//使用当前对象为监视器
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":卖票,票号为" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

2.使用【同步代码块】解决【继承Thread类】的线程安全问题
  • 在继承Thread类创建多线程的方式中,慎用this充当同步监视器。考虑使用当前类充当同步监视器。
class Window2 extends Thread {

    public static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (Window2.class) { //Window2.class 只会加载一次
                if (ticket > 0) {
                    System.out.println(getName() + ":卖票,票号为" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowTest2 {
    public static void main(String[] args) {
        Window2 t1 = new Window2();
        Window2 t2 = new Window2();
        Window2 t3 = new Window2();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

方式二:同步方法

如果操作共享数据的代码完整的声明在一个方法中,不妨就把此方法声明成同步的。

  • 同步方法仍然涉及到同步监视器,只是不需要显示声明。
  • 非静态的同步方法,同步监视器是:this
  • 非静态的同步方法,同步监视器是:当前类本身

3.使用【同步方法】解决【实现Runnable接口】的线程安全问题

class Window3 implements Runnable {
    public int ticket = 100;

    @Override
    public void run() {
        while (ticket!=0) {
            show();
        }
    }

    private synchronized void show(){ //同步监视器:this
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":卖票,票号为" + ticket);
            ticket--;
        }
    }
}

public class WindowTest3 {
    public static void main(String[] args) {
        Window3 w = new Window3();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

4.使用【同步方法】解决【继承Thread类】的线程安全问题
class Window4 extends Thread {

    public static int ticket = 100;

    @Override
    public void run() {
        while (ticket!=0) {
            show();
        }
    }

    private static synchronized void show(){ //同步监视器:Window4.class
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + ":卖票,票号为" + ticket);
            ticket--;
        }
    }
}

public class WindowTest4 {
    public static void main(String[] args) {
        Window4 t1 = new Window4();
        Window4 t2 = new Window4();
        Window4 t3 = new Window4();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/659126.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号