前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >为什么junit单元测试会关闭非守护进程

为什么junit单元测试会关闭非守护进程

作者头像
johnhuster的分享
发布于 2022-03-28 12:14:44
发布于 2022-03-28 12:14:44
37500
代码可运行
举报
文章被收录于专栏:johnhusterjohnhuster
运行总次数:0
代码可运行

在网上有不少人发现了这个问题,却没有说明这个问题背后的故事,今天笔者就从源头把这个问题解释下,先把demo程序中用到的两个类代码贴出来:

消费者类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Consumer implements Runnable{
	private final TransferQueue<String> queue;
	public Consumer(TransferQueue<String> queue) {
		this.queue = queue;
	}
	@Override
	public void run() {
		try {
			System.out.println("Consumer " + Thread.currentThread().getName() + queue.take());
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

生产者类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Producer implements Runnable {
	private final TransferQueue<String> queue;
	public Producer(TransferQueue<String> queue) {
		this.queue = queue;
	}
	
	private String produce() {
		return "随机数字" + (new Random().nextInt(100));
	}
	
	@Override
	public void run() {
		try {
			while (true) {
				if (queue.hasWaitingConsumer()) {
					queue.transfer(produce());
				}
				TimeUnit.SECONDS.sleep(2);
			}
		} catch (InterruptedException e){
			
		}
	}
}

接下来看下下面两段测试代码:

1、在main方法中测试,测试结果是非守护进程不会退出,消费者线程都能拿到数据,消费者线程拿到数据后就直接退出了,最后就会剩下生产者线程独自运行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /**
    **一段生产者消费者demo
    ***/
	public static void main(String[] args) {
		TransferQueue<String> queue = new LinkedTransferQueue<String>();
		Thread producer = new Thread(new Producer(queue));
		//producer.setDaemon(true);
		producer.start();
		for (int i = 0; i < 10; i++) {
			Thread consumer = new Thread(new Consumer(queue));
			//consumer.setDaemon(true);
			consumer.start();
			try {
				//防止进程提前结束
				Thread.sleep(1000L);
			} catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

2、在junit单元测试中测试上述代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @Test
     public void transferQueue() {
         println(Thread.currentThread().isDaemon());
         TransferQueue<String> queue = new LinkedTransferQueue<String>();
         Thread producer = new Thread(new Producer(queue));
         producer.setDaemon(true);
         println(producer.isDaemon());
         //producer.setDaemon(true);
         producer.start();
         for (int i = 0; i < 10; i++) {
             Thread consumer = new Thread(new Consumer(queue));
             //consumer.setDaemon(true);
             consumer.start();
             try {
                 //防止进程提前结束
                 Thread.sleep(1000L);
             } catch(InterruptedException e) {
                 e.printStackTrace();
             }
         }
         println("结束");
     }

上述代码执行结果是:大约5个消费者线程拿到数据后,整个程序退出,从 println(Thread.currentThread().isDaemon());输出我们可以看到运行单元测试的线程是个非守护线程,那么由该线程创建的生产者以及消费者线程也会继承父线程特性,成为非守护线程,我们都知道,非守护线程没结束前,JVM是不会退出的,那么这里为什么会出现这种情况呢,下面看下核心类org.eclipse.jdt.internal.junit.runner.RemoteTestRunner,这是用eclipse执行junit单元测试时用到的类,下面贴出单元测试执行的原理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	public static void main(String[] args) {
		try {
			RemoteTestRunner testRunServer= new RemoteTestRunner();
			testRunServer.init(args);
			testRunServer.run();
		} catch (Throwable e) {
			e.printStackTrace(); // don't allow System.exit(0) to swallow exceptions
		} finally {
			// fix for 14434
			System.exit(0);
		}
	}

从上面的代码可以看出当所有的单元测试都执行完毕后会调用System.exit(0)退出,这也就是为什么单元测试中非守护线程也会退出的原因!

参考文章:

1、https://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/tree/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/RemoteTestRunner.java?id=d0add1708b812c80384d88ef4eb52493b862187d

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/11/26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
多线程使用的关键字
  Synchronized修饰一个方法很简单,就是在方法的前面加synchronized,synchronized修饰方法和修饰一个代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数。
小勇DW3
2018/08/30
7250
多线程使用的关键字
Junit 多线测试 问题
问题 在使用Junit测试时,发现在测试方法中启动新的线程,结果新开启的线程未执行,测试方法就结束了。难道Junit不支持多线程测试? 示例如下: public class ThreadTest { @Test public void testSleep() { Thread t = new Thread(()-> { try { Thread.sleep(1000); } catch (Exce
java404
2018/05/18
1.4K0
Java 线程基础
简言之,进程可视为一个正在运行的程序。它是系统运行程序的基本单位,因此进程是动态的。进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动。进程是操作系统进行资源分配的基本单位。
静默虚空
2019/12/26
4750
Java 线程基础
Junit单元测试不支持多线程测试问题全解析
今天@段段提出了一个很好的问题,她发现单元测试时如果开多个线程,主线程运行结束就结束了,并不会等待子线程结束。
明明如月学长
2021/08/31
1.2K0
Junit单元测试不支持多线程测试问题全解析
守护线程和非守护线程_java守护线程的作用
Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
全栈程序员站长
2022/11/04
5640
守护线程和非守护线程_java守护线程的作用
Java多线程详解3
Java多线程详解 Java线程:线程的调度-休眠 Java线程调度是Java多线程的核心,只有良好的调度,才能充分发挥系统的性能,提高程序的执行效率。 这里要明确的一点,不管程序员怎么编写调度,只能最大限度的影响线程执行的次序,而不能做到精准控制。 线程休眠的目的是使线程让出CPU的最简单的做法之一,线程休眠时候,会将CPU资源交给其他线程,以便能轮换执行,当休眠一定时间后,线程会苏醒,进入准备状态等待执行。 线程休眠的方法是Thread.sleep(long millis)和Thread.sleep(l
Java帮帮
2018/03/15
7740
Java中的BlockingQueue1 Java中的阻塞队列2 生产者和消费者例子2 Java里的阻塞队列
1 Java中的阻塞队列 1.1 简介 一种支持两个附加操作的队列,是一系列阻塞队列类的接口 当存取条件不满足时,阻塞在操作处 队列满时,阻塞存储元素的线程,直到队列可用 队列空时,获取元素的线程会
JavaEdge
2018/05/16
1.6K0
thread 守护线程_守护线程与非守护线程
  Java中线程分为用户线程(user thread)和守护线程(daemon thread),它们通过Thread的daemon属性标识:true表示守护线程,false表示用户线程。   一个Thread初始默认为用户线程(daemon默认为false),创建Thread的时候默认从当前线程”继承”daemon属性,见Thread.init方法:
全栈程序员站长
2022/11/04
5030
系统学习javaweb-04-进程
线程:线程在一个进程中负责代码的执行,是进程中一个执行路径 多线程:在一个进程中有多个线程同时在执行不同的任务 一个java应用程序至少有两个线程,一个是主线程负责main方法代码的执行,一个是垃圾回收器线程,负责了回收垃圾。
csxiaoyao
2019/02/15
3450
Javva学也学不明白之多线程机制详解。
在java中,每个栈和每个栈之间互不干扰,各自执行各自的,这就是多线程并发。java中之所以有多线程机制,目的就是为了提高程序的处理效率。
百思不得小赵
2022/12/01
2360
Javva学也学不明白之多线程机制详解。
java线程详解(史上最全)
根据本人多年从业以及学习经验,录制了一套最新的Java精讲视频教程,如果你现在也在学习Java,在入门学习Java的过程当中缺乏系统的学习教程,你可以加QQ群654631948领取下学习资料,面试题,开发工具等,群里有资深java老师做答疑,每天也会有基础部分及架构的直播课,也可以加我的微信renlliang2013做深入沟通,只要是真心想学习Java的人都欢迎。
全栈程序员站长
2022/09/08
2650
java线程详解(史上最全)
守护线程是什么_守护线程什么时候结束
守护线程是程序运行的时候在后台提供一种通用服务的线程。所有用户线程停止,进程会停掉所有守护线程,退出程序。
全栈程序员站长
2022/11/03
6830
Java的多线程和高并发详解
多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。
北游
2021/06/30
1.4K0
Java的多线程和高并发详解
7.JUC线程高级-生产消费问题&虚假唤醒
生产消费问题在java多线程的学习中是经常遇到的问题 ,多个线程共享通一个资源的时候会出现各种多线程中经常出现的各种问题。
用户1212940
2022/04/13
1880
Java高并发与多线程网络编程
当JVM启动时,会创建一个非守护线程 main,作为整个程序的入口,以及多个与系统相关的守护线程。
devi
2021/08/19
1.4K0
Java高并发与多线程网络编程
Java 多线程系列(3) —— 守护线程
在 Java 中,守护线程的设置非常简单,我们只需要调用 Thread 类的 setDaemo(true) 就行。同时我们也可以使用 isDaemon() 方法来查看一个线程是否是守护线程。 【示例】
求和小熊猫
2020/12/02
4270
【说站】java守护线程的注意事项
1.守护线程的设置setDaemon(true)必须先放在start()之前,否则程序会出错。
很酷的站长
2022/11/23
1710
【说站】java守护线程的注意事项
Java 阻塞队列 BlockingQueue 介绍: put,add 和 offer 三个方法
在多线程编程中,经常需要使用线程安全的数据结构,用于在不同线程之间进行数据交换和通信。Java提供了一种称为阻塞队列(BlockingQueue)的数据结构,它是线程安全的队列实现,提供了一些特殊的方法来处理多线程环境下的数据交换问题。本文将介绍阻塞队列的基本概念和在Java中使用的三种常见方法:put,add和offer。
大盘鸡拌面
2023/11/02
8880
JAVA多线程详解
分为两种:一类是守护线程,典型是垃圾回收GC;第二类是用户线程,当JVM中都是JVM守护线程,那么当前的JVM将退出。
阮键
2019/08/07
4260
生产者消费者模式的三种实现方式
java中生产者消费者模式的三种实现方式 生产者消费者的实现 生产者生产数据到缓冲区中,消费者从缓冲区中取数据。 如果缓冲区已经满了,则生产者线程阻塞; 如果缓冲区为空,那么消费者线程阻塞。 wait notify方式实现 1. 生产者 package com.earthchen.ProducerConsumer.waitnotify; import java.util.Queue; /** * @author earthchen * @date 2018/9/20 **/ public cla
earthchen
2020/09/24
3270
相关推荐
多线程使用的关键字
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文