线程的生命周期
文章图片
在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5中状态。
当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他Java对象一样,仅仅由Java虚拟机为其分配内存,并初始化器成员变量的值。当线程对象调用start()方法之后,该线程就处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。但是它不可能一直处于运行状态(除非它的线程执行体足够短,瞬间就执行结束了),线程在运行过程中需要被中断,目的是是其他线程获得执行的机会,点成调度的细节取决于底层平台所采用的策略。对于采用抢占式策略的系统而言,系统会给每个可执行的线程一个小时间段来处理任务;当该时间段用完后,系统就会剥夺该线程所占用的资源,让其他线程获得执行的机会。在选择下一个线程时,系统会考虑线程的优先级。
等待和恢复与同步问题
等待和恢复简介
暂停线程意味着此线程还可以恢复运行。通过suspend()函数,可使线程进入停滞状态。使用顶级父类Object的wait()暂停, notify()唤醒方法。这两个方法,必须获得obj锁,也就是必须写在synchronized(obj) 代码段内。
通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回
可执行状态。注意如果在线程没有挂起时(就是没有调用suspend()方法前)去调用
Resume()方法会出现异常,所以使用这样的方法进行线程线程同步已经不推荐使用了。
同步问题
实际开发中,使用多线程程序的情况很多,如银行排号系统、火车站售票系统等。这种多线程的
程序通常会发生问题,以火车站售票系统为例,在代码中判断当前票数是否大于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 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|一个抽奖的例子演示线程的同步,暂停和恢复】
推荐阅读
- 笔记|初识Java Bean
- 程序员|手把手教你使用 Python 制作贪吃蛇游戏
- c++|Python 什么时候会被取代()
- 编程语言|Canvas渲染会取代DOM吗()
- Charles 抓包 Idea IntelliJ 的 HTTPS 请求
- C语言|C语言之调试技巧(VS2019编译器)
- 笔记|笔记17(C语言 实用调试技巧)
- ssh|计算机毕业设计springboot智慧问诊系统
- Java|JavaWeb - 黑马旅游网(1)(项目启动)