线程的生命周期
?在线程的生命周期中,它要经过新建(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);
}
}
|