多线程基础四(三)、暂停线程

暂停线程意味着此线程还可以回复运行。在 Java 多线程中,可以使用 suspend() 方法暂停线程,使用 resume() 方法恢复运行。

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++;
        }
    }
}
public class Test {
    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();
        }
    }
    /*
    运行结果:
    A = 1503631396807 i = 2771279480
    A = 1503631401807 i = 2771279480
    B = 1503631406807 i = 5576266494
    B = 1503631411807 i = 5576266494
     */
}
从结果上看到,线程的确是被暂停了,而且还能够恢复成运行状态。
缺点1:独占,在使用 suspend() 和 resume() 方法时,如果使用不当,会造成公共的同步对象的独占,使其他线程无法访问公共同步对象。
public class SynchronizedObject {
    public synchronized void printString() {
        if (Thread.currentThread().getName().equals("a")) {
            System.out.println("a 线程永远 suspend 了!");
            Thread.currentThread().suspend();
        }
        System.out.println("end");
    }
}
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() 方法!只打印一个 begin");
                    System.out.println("因为 printString() 方法被a线程锁定并且永远suspend暂停了!");
                    object.printString();
                }
            };
            thread2.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /*
    运行结果:
    a 线程永远 suspend 了!
    thread2 启动了,但进入不了 printString() 方法!只打印一个 begin
    因为 printString() 方法被a线程锁定并且永远suspend暂停了!
     */
}
thread1 执行 printString() 方法符合条件,所以线程 thread1 被暂停了,没有打印出 end(也没有释放 object 对象的锁,导致 thread2 不能执行  printString() 方法)
下面我们再看一个例子:
public class MyThread2 extends Thread {
    private long i = 0;
    @Override
    public void run() {
        while (true) {
            i++;
        }
    }
}
public class Test2 {
    public static void main(String[] args) {
        try {
            MyThread2 thread = new MyThread2();
            thread.start();
            Thread.sleep(1000);
            thread.suspend();
            System.out.println("main end!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /*
    运行结果:
    main end!
     */
}
但是如果将 MyThread2 修改成:
public class MyThread2 extends Thread {
    private long i = 0;
    @Override
    public void run() {
        while (true) {
            i++;
            System.out.println(i);
        }
    }
}
public class Test2 {
    public static void main(String[] args) {
        try {
            MyThread2 thread = new MyThread2();
            thread.start();
            Thread.sleep(1000);
            thread.suspend();
            System.out.println("main end!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /*
    运行结果:
    338787
    338788
    338789
    338790
    338791
     */
}
可以看到,结果将不在输出 main end 了,这是为什么?

其实是跟println() 方法有关,该方法是线程安全的。当 thread 执行该方法时持有方法的锁,thread.suspend() 之后,并没有释放锁,所以 main线程中吃吃不能输出 main end。



缺点2:不同步,在使用 suspend() 和 resume() 方法也容易出现因为线程的暂停而导致数据不同步的情况

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();
        }
    }

    public void printString() {
        System.out.println(username + " " + password);
    }
}
public class Run2 {
    public static void main(String[] args) throws InterruptedException {
        final MyObject myObject = new MyObject();
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                myObject.setValue("a", "aa");
            }
        };
        thread1.setName("a");
        thread1.start(); //启动线1,run方法中 username 由 1 变为 a,输出 停止a线程。同时暂停 thread1(没有释放对象myOjbect.setValue()的锁)
        Thread.sleep(500);
        Thread thread2 = new Thread() {
            @Override
            public void run() {
                myObject.printString();
            }
        };
        thread2.start();//启动线程2,运行printString() 方法,myOjbect.username 已经被 thread 改边为 a
    }
    /*
    运行结果:
    停止 a 线程!
    a 11
     */
}
总结:

1.  suspend() 和 resume() 方法可以暂停线程、重新启动线程,但是有缺陷。

2. 缺陷一:独占,在使用 suspend() 和 resume() 方法时,如果使用不当,会造成公共的同步对象的独占,使其他线程无法访问公共同步对象

3. 缺陷二:不同步,在使用 suspend() 和 resume() 方法也容易出现因为线程的暂停而导致数据不同步的情况


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值