前篇说到了Thread中的join方法,这一篇我们就来介绍一下suspend()和resume()方法,从字面意义上可以了解到这两个方法是一对的,suspend()方法就是将一个线程挂起(暂停),resume()方法就是将一个挂起线程复活继续执行。首先看一个例子:

package com.threadstop.demo;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; /**
 * @author weijiang204321
 *说明:
 *调用了suspend方法,将t0线程挂起,但是出现的问题是,t0.suspend方法之后的代码不执行了,搞了半天终于知道为什么了,
 *因为在t0里面使用了System.out.println方法了,查看println方法的源代码发现他是个同步的方法,加锁了,这个锁是哪个呢?
 *对就是PrintStream,在Main中的printCurrentAliveThread方法中用到了System.out.println方法,打断点才知道
 *搞了半天阻塞在这里了,因为我们知道suspend方法是不释放锁的,所以导致会阻塞在println方法中,但是有一个前提是t0线程和main线程
 *的println方法中拿到的是同一个锁,这时候在看一下System.out变量时一个static PrintStream,这时候就明了了,因为是static
 *所以对象是相同的,这两个线程拿到的System.out是同一个对象,所以这两个线程也是拿到的是相同的锁的。
 *
 */ public class ThreadStopLock { public static void main(String[] args) {
try {
//定义线程
Thread t0 = new Thread() {
public void run() {
try {
for(long i=0;i<1000*1000*10;i++){
System.out.println(i);
}
System.out.println("thread death");
} catch (Throwable ex) {
System.out.println("Caught in run: " + ex);
ex.printStackTrace();
}
}
};
//开启线程
t0.start();
//等待2s之后挂起线程t0
Thread.sleep(2*1000);
//挂起线程
t0.suspend();
//打印当前的所有线程
printCurrentAliveThread();
//等待2s之后恢复线程
Thread.sleep(2*1000);
//复活线程
t0.resume(); } catch (Throwable t) {
System.out.println("Caught in main: " + t);
t.printStackTrace();
} } /**
* 打印当前线程
*/
public static void printCurrentAliveThread(){
Map<Thread, StackTraceElement[]> maps = Thread.getAllStackTraces();
Set<Entry<Thread, StackTraceElement[]>> set = maps.entrySet();
Iterator<Entry<Thread,StackTraceElement[]>> iterator = set.iterator();
System.out.println("System Alive Thread List:");
System.out.println("-------------------------");
while(iterator.hasNext()){
System.out.println("AliveThread_Name:"+iterator.next().getKey().getName());
}
System.out.println("-------------------------");
} }

代码很简单的,定义一个线程,在线程中进行打印,在主线程中的逻辑是,先开启线程t0进行打印数据,等待2s之后将挂起线程t0,然后打印一下当前的活跃线程,然后再等待2s之后再复活t0线程继续打印!

但是结果不尽人意呀,结果很是惊讶的!运行结果:

好吧,开始打印,打印到311800(当然这个不是一定的),就停止了,但是这一停止不是停2s呀,是一直停着,这不是明显的死锁吗?导致t0.suspend后面的代码都不执行了,这就郁闷了,这个是为什么呢?纠结了一下午,打断点的时候才知道为什么,断点停在方法printCurrentAliveThread中的System.out.println()这行代码上,那就可以断定了,发生死锁的原因可能就是System.out.println方法,查看源代码:

 public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}

这个是PrintStream对象中的println方法,是个同步锁的方法,这时候应该就明白了,那么这个锁是什么呢?没错,这个所就是PrintStream对象,因为在t0线程中也有System.out.println,当调用suspend()方法调用的时候,这个方法是不会释放锁的,当然这个锁是同一个的,为什么呢?看一下System类中的out变量定义:

 public final static PrintStream out = null;

是static类型的,所以他是类上面的锁,肯定是同一个锁了,所以发生了死锁,

这时候我们将printCurrentAliveThread方法注释之后,运行就没有任何问题了。

就写到这里吧,好累,后面还有哦,继续关注吧!

Java中的线程Thread方法之---suspend()和resume()的更多相关文章

  1. Java中的线程Thread方法之---interrupt()

    前几篇都介绍了Thread中的几个方法,相信大家都发现一个相似点,那就是sleep,join,wait这样的阻塞方法都必须捕获一个InterruptedException异常,顾名思义就是一个线程中断 ...

  2. Java中的线程Thread方法之---stop()

    搞过Java线程的人都知道,stop这个方法是臭名昭著了,早就被弃用了,但是现在任然有很多钟情与他的人,永远都放不下他,因为从他的字面意思上我们可以知道他貌似可以停止一个线程,这个需求是每个搞线程开发 ...

  3. Java中的线程Thread方法之---join()

    上一篇我们说到了Thread中的stop方法,这一篇我们再来看一下方法join的使用,那么方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. join方法从字面上的意 ...

  4. Java中的线程Thread总结

    首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的! 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口. 要注意的是Threa ...

  5. Java中实现线程的方法

    Java中有几种方法可以实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用? 第一种:继承Thread类 new Thread(){}.start();这表示调 ...

  6. Java 中的线程 thread

    一.问:线程有哪些状态? new, runnable, running, waiting, dead 线程状态间的流转 二.问:线程实现方式? 实现 Runnable 接口,然后new Thread, ...

  7. JAVA中创建线程的三种方法及比较

    JAVA中创建线程的方式有三种,各有优缺点,具体如下: 一.继承Thread类来创建线程 1.创建一个任务类,继承Thread线程类,因为Thread类已经实现了Runnable接口,然后重写run( ...

  8. JAVA中创建线程池的五种方法及比较

    之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...

  9. 【Java中的线程】java.lang.Thread 类分析

    进程和线程 联想一下现实生活中的例子--烧开水,烧开水时是不是不需要在旁边守着,交给热水机完成,烧开水这段时间可以去干一点其他的事情,例如将衣服丢到洗衣机中洗衣服.这样开水烧完,衣服洗的也差不多了.这 ...

随机推荐

  1. PHP-缺失的第一个正数

    给定一个未排序的整数数组,找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0]输出: 3示例 2: 输入: [3,4,-1,1]输出: 2示例 3: 输入: [7,8,9,11,12] ...

  2. nodejs模块——fs模块 使用fs.read读文件

    使用fs.read读文件 fs.read() 先介绍fs.open. fs.open(path,flags,[mode],callback)方法用于打开文件,以便fs.read()读取. 参数说明: ...

  3. 【leetcode】973. K Closest Points to Origin

    题目如下: We have a list of points on the plane.  Find the Kclosest points to the origin (0, 0). (Here, ...

  4. JQuery 浮动DIV显示提示信息并自动隐藏

    /** * 浮动DIV定时显示提示信息,如操作成功, 失败等 * @param string tips (提示的内容) * @param int height 显示的信息距离浏览器顶部的高度 * @p ...

  5. SQL SELECT DISTINCT

    SQL SELECT DISTINCT(选择不同) 语法 SELECT DISTINCT语法用于仅返回不同的(different)值. 在一张表内,一列通常包含许多重复的值; 有时你只想列出不同的(d ...

  6. java中文件下载的思路(参考:孤傲苍狼)

    文件下载 文件下载功能是web开发中经常使用到的功能,使用HttpServletResponse对象就可以实现文件的下载 文件下载功能的实现思路: 1.获取要下载的文件的绝对路径 2.获取要下载的文件 ...

  7. 【LeetCode 1】两数之和

    描述 [题解] 用个map的话就是O(N)级别的了. [代码] class Solution { public: unordered_map<int,int> mymap; vector& ...

  8. Android中的RelativeLayout中组件的排放问题

    今天想仿照新浪微博的用户中心 主要就是那个头像的问题,这个看到就想到用相对布局,现在是我想把那个名称放到头像的上面去xml中定义如下: <RelativeLayout android:layou ...

  9. 画山 paint

    画山 paint 有一张大小为n*m的白纸,小R想在纸上画一片绵延的群山. 为了描述方便,我们将纸张表示在坐标系上,四个顶点的坐标分别为(0,0),(n,0),(0,m),(n,m). 小R有一只神奇 ...

  10. 【UR #2】跳蚤公路

    [UR #2]跳蚤公路 参照yjc方法.也就是地铁环线那个题. 求每个点不在负环内的x的取值范围.然后所有1到j能到i的j的范围取交.得到答案. 每个边形如kx+b的直线,每个环也是 每个点不在负环内 ...