如何暂停线程?

x33g5p2x  于2021-12-18 转载在 其他  
字(3.0k)|赞(0)|评价(0)|浏览(318)

一、基础用法

和终止线程不同,暂停线程意味着此线程还可以恢复,在 Java 中,可以使用 suspend() 方法暂停线程,然后使用 resume() 方法恢复线程的执行。

首先通过一个例子来了解一下这两个方法的基础用法,代码如下:

public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        
        System.out.println("线程开始执行");
        myThread.start();
        Thread.sleep(100);
        System.out.println(myThread.getI());
        System.out.println(myThread.getI());
        System.out.println(myThread.getI());
        
        System.out.println("线程暂停执行");
        myThread.suspend();
        Thread.sleep(100);
        System.out.println(myThread.getI());
        System.out.println(myThread.getI());
        System.out.println(myThread.getI());
        
        System.out.println("线程恢复执行");
        myThread.resume();
        Thread.sleep(100);
        System.out.println(myThread.getI());
        System.out.println(myThread.getI());
        System.out.println(myThread.getI());
    }
}

class MyThread extends Thread {
    private long i = 0;

    public long getI() {
        return i;
    }

    public void setI(long i) {
        this.i = i;
    }

    @Override
    public void run() {
        while (true) {
            i++;
        }
    }
}

控制台输出如下:

线程开始执行
168569210
168612106
168619437
线程暂停执行
168657087
168657087
168657087
线程恢复执行
336960390
337119218
337155923

代码主要分为三部分,分别是开始、暂停和恢复,对应控制台的输出我们可以很清楚地看到:在开始和暂停之间的三次输出是不同的,说明线程正在运行;在暂停和恢复之间的三次输出是一样的,说明线程已暂停;在恢复之后的三次输出是不同的,说明线程已恢复执行。

二、缺点

使用这两种方法进行线程的暂停与恢复很容易出现独占锁数据不完整的情况。下面我会对这两种情况分别举例说明。

2.1 独占锁

public class Run {
    public static void main(String[] args) throws InterruptedException {
        SynchronizedObject synchronizedObject = new SynchronizedObject();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                synchronizedObject.printString();
            }
        };
        t1.setName("a");
        t1.start();

        Thread.sleep(1000);

        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "确实开启了线程");
                synchronizedObject.printString();
                System.out.println("但我是不会输出的");
            }
        };
        t2.setName("b");
        t2.start();
    }
}

class SynchronizedObject {
    synchronized public void printString() {
        System.out.println("-----start-----");
        if ("a".equals(Thread.currentThread().getName())) {
            System.out.println("线程 a 永远暂停了!");
            Thread.currentThread().suspend();
        }
        System.out.println("------end------");
    }
}

控制台输出:

-----start-----
线程 a 永远暂停了!
b确实开启了线程

线程 a 先执行 printString() 方法,在输出控制台的前两行后又执行了 suspend() 方法永久暂停了线程,并且没有释放对象锁;然后线程 b 开始执行,等到执行 printString() 方法时因为无法获取对象锁而无法继续执行。

2.2 数据不完整

public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyObject myObject = new MyObject();
        Thread thread = new Thread() {
            @Override
            public void run() {
                myObject.setValue("zmy", "123");
            }
        };
        thread.setName("a");
        thread.start();
        Thread.sleep(2000);
        myObject.printString();
    }
}

class MyObject {
    private String username = "root";
    private String password = "root";

    public void setValue(String username, String password) {
        this.username = username;
        if ("a".equals(Thread.currentThread().getName())) {
            System.out.println("暂停线程 a!");
            Thread.currentThread().suspend();
        }
        this.password = password;
    }

    public void printString() {
        System.out.println("username = " + this.username);
        System.out.println("password = " + this.password);
    }
}

控制台输出如下:

暂停线程 a!
username = zmy
password = root

相关文章