一个抽奖的例子演示线程的同步,暂停和恢复

线程的生命周期

 在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5中状态。

       当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他Java对象一样,仅仅由Java虚拟机为其分配内存,并初始化器成员变量的值。当线程对象调用start()方法之后,该线程就处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。但是它不可能一直处于运行状态(除非它的线程执行体足够短,瞬间就执行结束了),线程在运行过程中需要被中断,目的是是其他线程获得执行的机会,点成调度的细节取决于底层平台所采用的策略。对于采用抢占式策略的系统而言,系统会给每个可执行的线程一个小时间段来处理任务;当该时间段用完后,系统就会剥夺该线程所占用的资源,让其他线程获得执行的机会。在选择下一个线程时,系统会考虑线程的优先级

等待和恢复与同步问题

等待和恢复简介

 暂停线程意味着此线程还可以恢复运行。通过suspend()函数,可使线程进入停滞状态。
 通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回
 可执行状态。注意如果在线程没有挂起时(就是没有调用suspend()方法前)去调用
Resume()方法会出现异常,所以使用这样的方法进行线程线程同步已经不推荐使用了。

使用顶级父类Object的wait()暂停, notify()唤醒方法。这两个方法,必须获得obj锁,也就是必须写在synchronized(obj) 代码段内。

同步问题

实际开发中,使用多线程程序的情况很多,如银行排号系统、火车站售票系统等。这种多线程的
程序通常会发生问题,以火车站售票系统为例,在代码中判断当前票数是否大于0,如果大于。则执行把火车票出售给乘客的功能,但当两个线程同时访问这段代码时(假如这时只剩下一个线程將票售出,与此同时第二个线程也已经执行并完成判断是否有票的探作,并得出结论票数大于0,于是它也执行将票售出的操作,这样票数就会产生负数。所以在编写多线程程序时,应该考虑到线
程安全问题。实质上,线程安全问题来源于两个线程同时操作单一对象的数据。

这些方法并不是JDK自带的,而是我们写的方法。

同步块:

        synchronized (Object){
            
        }

可以有效防止资源冲突,同步机制使用synchronized关键字,使用该关键字的代码块称为同步块。


通常将共享资源的操作放置在 synchronized 定义的区域内,这样当其他线程获取到这个锁时,就
必须等待锁被释放后才可以进入该区域。Object 为任意一个对象,每个对象都存在一个标志位,并具有两个值,分别为0和1,一个线程运行到同步块时 首先检查该对象的标识位,如果为0状态,表明此同步块内存在其他线程,这时当前线程处于就绪状态,直到处于同步 块中的线程执行完同步块中的代码后,这时该对象的标识位设置为1,当前线程才能开始执行同步块中的代码,并将 Object 对象的标识位设罝为0,以防止其他线程执行同步块中的代码。
 

抽奖例子

代码

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class Zant extends JFrame {
    private JLabel l;
    String []number={"123456","248207","128181","234772","123423"};
    public Zant(){
        myThread t=new myThread();
        setTitle("手机号抽奖");
        setBounds(200,200,300,150);
        l=new JLabel("0");
        l.setHorizontalAlignment(SwingConstants.CENTER);
        l.setForeground(Color.RED);
        l.setFont(new Font("宋体",Font.PLAIN,42));
        JButton b=new JButton("暂停");
        add(l,BorderLayout.CENTER);
        add(b,BorderLayout.SOUTH);
        b.addActionListener(e -> {
            String str=b.getText();
            if (str.equals("暂停")){
                t.changeflag1();
                b.setText("继续");
            }else {
                b.setText("暂停");
                t.changeflag2();
            }
        });
        t.start();
    }
    class myThread extends Thread{
        boolean flag=false;
        public synchronized  void changeflag1(){
            flag=true;
        }

        public synchronized  void changeflag2(){
            flag=false;
            notify();
        }
        public  void run(){
            do {
                synchronized (this) {
                    while (flag) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                int i = new Random().nextInt(number.length);
                String name = number[i];
                l.setText(name);
            } while (true);
        }
    }
    public static void main(String[] args) {
        new Zant().setVisible(true);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_52473454/article/details/124504082