1.8暂停线程

在java中,使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。

1.8.1suspend与resume的使用:

线程代码:

public class Thread1 extends Thread {
    private long i = 0L;

    public long getI() {
        return i;
    }

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

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

执行代码:

public class Main {
    public static void main(String[] args) {
        try {
            Thread1 thread = new Thread1();
            thread.start();
            Thread.sleep(1000);
            //A段
            thread.suspend();
            System.out.println("A = " + System.currentTimeMillis() + " I = " +thread.getI());
            //B段
            thread.resume();
            Thread.sleep(1000);
            //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();
        }
    }
}

执行结果:

从执行的时间来看,新开启的线程确实发生了暂停(当前线程暂停与启动的时间与另外开启的线程是一致的),并且能够成功的恢复运行状态。

1.8.2suspend与resume方法的缺点——独占:

在使用suspend与resume方法时,可能会导致公共的同步对象的独占发生,使得其他线程无法访问公共同步对象。

独占代码:

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

执行代码:

public class Main {
    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("因为在Thread1中已经暂停了,后面的语句无法执行,所有只打印了begin");
                    System.out.println("因为此时Thread1已经进入了线程并且锁定了方法printString()所以什么都打不出来");
                    System.out.println("这是死锁的一种表现");
                    object.printString();
                }
            };
            thread2.setName("a");
            thread2.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

另一种陷阱式的多线程独占问题

线程代码:

public class Thread2 extends Thread {
    private long i = 0L;
    @Override
    public void run() {
        while (true) {
            i++;
            System.out.println(i);
        }
    }
}

执行代码:

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

执行结果:

卡在数字后面,并没有打印出main end。

原因是在于println()方法,查看其源码会更加清晰:

由源码可以得知,在println内部存在同步锁,当线程在println()内部停止时,同步锁就永远不会释放,就会导致死锁。  

1.8.3suspend与resume方法的缺点——不同步:

使用这两个方法容易出现数据不同步的情况。

共享数据类:

public class MyObject {
    private String username = "1";
    private String password = "11";
    public void setValue(String u,String p) {
        this.username = u;
        if("a".equals(Thread.currentThread().getName())) {
            System.out.println("停止a线程");
            Thread.currentThread().suspend();
        }
        this.password = p;
    }
    public void printUsernamePassword() {
        System.out.println(username + "|||" + password);
    }
}

执行代码:

public class Main {
    public static void main(String[] args) {
        try {
            final MyObject object = new MyObject();
            Thread thread = new Thread() {
                @Override
                public void run() {
                    object.setValue("a","aa");
                }
            };
            thread.setName("a");
            thread.start();
            Thread.sleep(1000);
            Thread thread1 = new Thread() {
                @Override
                public void run() {
                    object.printUsernamePassword();
                }
            };
            thread1.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

源码地址:https://github.com/lilinzhiyu/threadLearning

本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术

那些鲜为人知的序列化和反序列化底层实现原理!

序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列...

752
来自专栏xingoo, 一个梦想做发明家的程序员

const指南

基本词义  意思就就是说利用const进行修饰的变量的值在程序的任意位置将不能再被修改,就如同常数一样使用!  使用方法 const int a=1;//这里定...

18710
来自专栏C语言及其他语言

Python程序员最常犯的十个错误

来源:编程派 ? 不管是在学习还是工作过程中,人都会犯错。虽然Python的语法简单、灵活,但也一样存在一些不小的坑,一不小心,初学者和资深Python程序...

3117
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-day01-基础题

1. 简述java语言,具有哪些特性? (1).java语言是简单的 java语言是和c++语言类似的,其次java中丢弃了c++中一些难理解的特性,比如运算符...

2684
来自专栏SpringBoot

提升Java性能

代码 优化 ,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面...

1163
来自专栏程序员互动联盟

【答疑释惑】C++异常处理是咋回事?

疑惑一 C++的异常处理 一、什么是异常处理 一句话:异常处理就是处理程序中的错误。 二、为什么需要异常处理,以及异常处理的基本思想 C++ 之父Bjarne ...

3205
来自专栏北京马哥教育

Python程序员最常犯的十个错误,看完你自己都笑了

本文由马哥教育Python自动化实战班4期学员推荐,转载自简书,作者为EarlGrey,内容略经小编改编和加工,观点跟作者无关,最后感谢作者的辛苦贡献与付出。 ...

2744
来自专栏前端说吧

【消灭代办】第一周 - 敏感词判断

  一堆字符串组成的数组,给你一个字符串,让你去查找这个字符串是否在这个数组当中?

701
来自专栏CDA数据分析师

Python | 十个Python程序员易犯的错误

不管是在学习还是工作过程中,人都会犯错。虽然Python的语法简单、灵活,但也一样存在一些不小的坑,一不小心,初学者和资深Python程序员都有可能会栽跟头。本...

19810
来自专栏FreeBuf

PHP代码安全杂谈

虽然PHP是世界上最好的语言,但是也有一些因为弱类型语言的安全性问题出现。WordPress历史上就出现过由于PHP本身的缺陷而造成的一些安全性问题,如CVE-...

2556

扫码关注云+社区