线程暂停与恢复研究

方法一:suspend()与resume()

使用方法(使用最方便)

Thread t = new Thread(new MyThread());

t.suspend();//暂停

t.resume();//恢复

线程t在运行到suspend()之后被强制挂起,暂停运行,直到主线程调用t.resume()方法时才被重新唤醒。

目前已经废弃了suspend()和resume()方法,因为使用这两个方法可能会产生死锁(挂起时,不释放资源),所以应该使用同步对象调用wait()和notify()的机制来代替suspend()和resume()进行线程控制。

 

方法二:wait()与notify() (更多是用在线程同步中的)

 

wait()导致当前的线程等待,直到其他线程调用此对象的 notify() 或 notifyAll() 为止。

要实现wait()和notify()我们必须具备一把对象锁(每个对象,每个类其实都是有自己独特的一把锁的),如图中间方框为指定对象的对象锁(对象随便指定,没有其他意义,如public static Integer lock = 0; lock其实就是一个对象),那么怎么获取指定对象的对象锁呢?

通过synchronized(lock){//···}实现获取对象锁,注意:如果每个线程都用这个方法修饰,那么一次只能有一个线程获得指定对象的对象锁(随机指定哪个线程获得),其他线程只能是处于阻塞状态,当获得对象锁的线程执行完synchronized(lock){//···}中的代码,才会释放对象锁,其他线程继续争夺对象锁,直到全部执行完毕。如图所示。

synchronized(lock){//···}其实就是相当于临界资源,对于括号里的代码最多只能有1个访客使用,相当于互斥。

图解释:

左边1,2为两个优先级相同的线程。

左边方块表示线程1,2争夺对象锁

上面箭头1表示1获得对象锁,转到右边框执行线程1中synchronized(lock){//···}中的内容,如{}中内容是lock.wait();表示当自己抢到对象锁的时候执行下面代码,把自己挂起。直到其他有人使用lock.notify()把自己唤醒。

挂起的时候同时释放自己资源(不会造成死锁),释放对象锁,让其他线程争夺使用······

 

如下图用wait()和notify()来实现一个线程的暂停和恢复的一个错误

想法是通过设定bl的值来实现线程的暂停和恢复,当bl = true时唤醒,当bl=false时暂停。

调试显示第二行While(true)用来监听的死循环只执行了一次,根本没有达到预期一直执行的效果。那是为什么呢?

因为要实现点击开始执行一开始肯定要是挂起状态,so bl的初值是false;按照想法的到了else中执行lock.wait();挂起了当前线程,也就是说run()挂起不执行;所以再通过改变bl值去判断唤醒显然行不通。解决方法是:1.通过其他线程来唤醒  2.通过在run()上面定义方法来实现notify();当调用方法时实现唤醒。因此想到可以定义两个方法,一个实现线程的暂挂,一个实现恢复,实现发现毫无意义,不如通过方法三来实现。


 

方法三:自己实现

主要使用Boolean bl = false;通过设定bl的值来实现线程暂停 运行效果。

run(){

  while(true){ //起到监听作用

    while(bl){

         system.out.println(i++);

    }

  }

}

 

 

下面是实验代码:

方法一:有界面,通过点击begin按钮实现开始,点击pause按钮实现线程暂停,方法三也是如此界面。

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test1 {
public static MyThread mythread;
public static Thread t;

public static void main(String args[]){
new MyFrame();

mythread = new MyThread();
t = new Thread(mythread);

t.start();
t.suspend();

}

static class MyFrame implements ActionListener{
JFrame f;
JPanel p;
JButton b1, b2;
public MyFrame(){
f = new JFrame();
p = new JPanel();

b1 = new JButton("begin");
b2 = new JButton("pause");

b1.setSize(new Dimension(60,10));
b2.setSize(new Dimension(30,10));

b1.addActionListener(this);
b2.addActionListener(this);

p.setLayout(new GridLayout(1,2,10,0));
p.add(b1);
p.add(b2);

f.add(p);
f.setBounds(300, 300, 300, 100);
f.setVisible(true);


}

public void actionPerformed(ActionEvent e) {
if(e.getSource() == b1){
t.resume();
}

if(e.getSource() == b2){
t.suspend();
}
}
}


static class MyThread implements Runnable{
int i=0;
public void run(){ //关键在于run()只执行一次!!!!
while(true){
System.out.println(i++);
}
}
}
}



方法二:因为不适合暂停,恢复,在这里不讨论这个问题,我们实现线程的同步问题。

实现t2永远比t1先执行public class Test1 {
public static final Integer x = 0;
public static int y = 0;

public static void main(String args[]) throws InterruptedException {
for (int i = 0; i < 5; i++)
System.out.println("lalala");

Thread t1 = new Thread(new MyThread1());
Thread t2 = new Thread(new MyThread2());

t1.start();
t2.start();

}

}

// synchronized
class MyThread1 implements Runnable {
boolean is = true;

public void run() {
synchronized (Test1.x) {
try {
Test1.x.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("1");
}
}
}

class MyThread2 implements Runnable {
public void run() {
synchronized (Test1.x) {
System.out.println("2");
Test1.x.notifyAll();
}
}
}  方法三:自己方法实现线程暂停,恢复。import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test1 {
public static MyThread mythread;

public static void main(String args[]){
new MyFrame();

mythread = new MyThread();
Thread t = new Thread(mythread);

t.start();

}

static class MyFrame implements ActionListener{
JFrame f;
JPanel p;
JButton b1, b2;
public MyFrame(){
f = new JFrame();
p = new JPanel();

b1 = new JButton("begin");
b2 = new JButton("pause");

b1.setSize(new Dimension(60,10));
b2.setSize(new Dimension(30,10));

b1.addActionListener(this);
b2.addActionListener(this);

p.setLayout(new GridLayout(1,2,10,0));
p.add(b1);
p.add(b2);

f.add(p);
f.setBounds(300, 300, 300, 100);
f.setVisible(true);


}

public void actionPerformed(ActionEvent e) {
if(e.getSource() == b1){
mythread.begin();
}

if(e.getSource() == b2){
mythread.pause();
}
}
}


static class MyThread implements Runnable{
int i = 0;
Boolean bl = false;

public void begin(){
bl = true;
}

public void pause(){
bl = false;
}


public void run(){ //关键在于run()只执行一次!!!!
while(true){
while(bl)
System.out.println(i++);
}
}
}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值