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

线程的生命周期 java|一个抽奖的例子演示线程的同步,暂停和恢复
文章图片

在线程的生命周期中,它要经过新建(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,于是它也执行将票售出的操作,这样票数就会产生负数。所以在编写多线程程序时,应该考虑到线
程安全问题。实质上,线程安全问题来源于两个线程同时操作单一对象的数据。
java|一个抽奖的例子演示线程的同步,暂停和恢复
文章图片


这些方法并不是JDK自带的,而是我们写的方法。
同步块:
synchronized (Object){}

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

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

抽奖例子 java|一个抽奖的例子演示线程的同步,暂停和恢复
文章图片


代码
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 synchronizedvoid changeflag1(){ flag=true; }public synchronizedvoid changeflag2(){ flag=false; notify(); } publicvoid 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); } }

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

    推荐阅读