暂停线程意味着此线程还可以恢复运行

在 Java 多线程中,可以使用 suspend()方法暂停线程,使用 resume() 方法来恢复线程的执行。



本节将讲述suspend()方法与resume()方法的使用

文件 MyThread.java代码

package test1_12;

public 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++;
        }
    }
}

文件Run.java代码

package test1_12;

public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(5000);
            // A段
            thread.suspend();
            System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
            Thread.sleep(5000);
            System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
            // B段
            thread.resume();
            Thread.sleep(5000);
            // C段
            thread.suspend();
            System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
            Thread.sleep(5000);
            System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

JAVA实现线程暂停 java 暂停线程_开发语言

 


从控制台输出的时间上来看,线程的确被暂停了,而 且可以恢复成运行状态。


stop()方法用于销毁线程对象,如果想继续运行线程, 则必须使用start()方法重新启动线程,

而suspend()方法用于让线程不再执行任务,线程对象并不销毁,在当前所执行 的代码处暂停,未来还可以恢复运行。

suspend()方法与resume()方法的缺点——独占

如果 suspend() 方法与 resume()方法使用不当,极易造成公共同步对象被 独占,其他线程无法访问公共同步对象的结果。

文件SynchronizedObject.java代码

package test1_12.test1;

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

文件Run.java代码

package test1_12.test1;

public class Run {
    public static void main(String[] args) {
        try {
            final SynchronizedObject object = new SynchronizedObject();
            Thread thread1 = new Thread() {
                @Override
                public void run() {
                    object.printString();
                }
            };
            thread1.setName("a");
            thread1.start();
            Thread.sleep(1000);
            Thread thread2 = new Thread() {
                @Override
                public void run() {
                    System.out.println("thread2启动了,但进入不了printString()方法!只打印1个begin");
                    System.out.println("因为printString()方法被a线程锁定并且永远suspend暂停了!");
                    object.printString();
                }
            };
            thread2.start();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

运行结果

JAVA实现线程暂停 java 暂停线程_System_02

另外一种独占锁的情况也需要格外注意,稍有不注意,就会掉 进“坑”里。

类MyThread.java 代码

package test1_12.test2;

public class MyThread extends Thread {
    private long i = 0;

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

类Run.java代码

package test1_12.test2;

public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(1000);
            thread.suspend();
            System.out.println("main end!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

JAVA实现线程暂停 java 暂停线程_开发语言_03

进程状态在控制台中呈红色按钮显示,说明进程并未销毁。虽然main 线程销毁了,但是 MyThread 呈暂停状态,所以进程不会销毁。

但如果将线程类MyThread.java更改如下

package test1_12.test3;

public class MyThread extends Thread {
    private long i = 0;

    @Override
    public void run() {
        while (true) {
            i++;
            System.out.println(i);
        }
    }
}

运行结果




JAVA实现线程暂停 java 暂停线程_JAVA实现线程暂停_04


再次运行程序,控制台不输出 main end

出现这种情况的原因是当程序运行到System.out.println (i)方法内部 停止时,同步锁是不释放的

println()方法源代码

/**
     * Prints a String and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(String)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @param x  The <code>String</code> to be printed.
     */
    public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

当前 PrintStream 对象的 println() 方法一直呈 “ 暂停 ” 状态,并且 “锁未释 放 ” ,而 main() 方法中的代码 “System.out.println ( "main end ! " ); ”也需要 这把锁, main 线程并未销毁,造成迟迟不能输出 main end。

虽然 suspend() 方法是过期作废的方法,但研究其过期作废的原因是很

有必要的。

suspend()方法与resume()方法的缺点—— 数据不完整

在使用suspend()方法与resume()方法时也容易出现线 程暂停,进而导致数据不完整的情况。

文件 MyObject.java代码

package test1_12.test4;

public class MyObject {
    private String username = "1";
    private String password = "11";

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

    public void printUsernamePassword() {
        System.out.println(username + " " + password);
    }
}

文件Run.java代码

package test1_12.test4;

public class Run {
    public static void main(String[] args) throws InterruptedException {
        final MyObject myobject = new MyObject();
        Thread thread1 = new Thread() {
            public void run() {
                myobject.setValue("a", "aa");
            }

            ;
        };
        thread1.setName("a");
        thread1.start();
        Thread.sleep(500);
        Thread thread2 = new Thread() {
            public void run() {
                myobject.printUsernamePassword();
            }

            ;
        };
        thread2.start();
    }
}

运行结果

JAVA实现线程暂停 java 暂停线程_java代码_05

程序运行结果出现值不完整的情况,所以在程序中使 用 suspend() 方法要格外注意。


这两个方法被标识为作废过期的,想要实现对线程进 行暂停与恢复的处理,可使用 wait() 、 notify() 或notifyAll() 方法