线程组

线程组的核心在于方便批量管理同一类线程,定义线程的共性行为。比如某个线程出现异常,则中断该组中所有线程。

推荐博文 https://www.cnblogs.com/noteless/p/10354721.html#

1. 私有的无参构造方法会构造一个system线程组,也被称之为根线程组。该方法由C代码调用

   /**
     * Creates an empty Thread group that is not in any Thread group.
     * This method is used to create the system Thread group.
     */
    private ThreadGroup() {     // called from C code
        this.name = "system";
        this.maxPriority = Thread.MAX_PRIORITY;
        this.parent = null;
    }

1. 从构造方法上来看,每个线程组(非system)必定有它的父线程组,不指定的话,默认为当前线程所属的线程组  Thread.currentThread().getThreadGroup()

public ThreadGroup(String name) {
    this(Thread.currentThread().getThreadGroup(), name);
}

public ThreadGroup(ThreadGroup parent, String name) {
    this(checkParentAccess(parent), parent, name);
}

private ThreadGroup(Void unused, ThreadGroup parent, String name) {
    this.name = name;
    this.maxPriority = parent.maxPriority;
    this.daemon = parent.daemon;
    this.vmAllowSuspension = parent.vmAllowSuspension;
    this.parent = parent;
    parent.add(this);
}

 

2. 从线程Thread的核心构造方法来看,如果线程在创建时不指定所属线程组,默认为父线程(姑且称之)所属的线程组,但是要注意的是,这里只是指定了父线程组,至于线程组中用来记录并存储组中线程的容器数组 Thread threads[] 并未加入该线程,仅当线程调用start方法并成功启动后,才算真正加入。

联系Thread中的方法可知,

3. 有关线程组的枚举方法,虽然没用过,这里简单分析一下枚举线程组中的线程,枚举子线程组的方法与其类似,跳过

/**
 * 参数list,一个用来装线程对象的数组容器,方法调用者自己传入,通常为一个空容器
 * 参数recurse,是否递归取得所有子孙组中的线程对象,默认为true
 * 参数n,调用者无法传入,公有的enumerate方法中未设置该参数,默认为0,在递归时被赋值,保证放入的线程对象不超出list长度
 */    
private int enumerate(Thread list[], int n, boolean recurse) {
        int ngroupsSnapshot = 0;
        ThreadGroup[] groupsSnapshot = null;
        synchronized (this) {
            if (destroyed) {
                return 0;
            }
            // nthreads表示该组中的所有线程数
            int nt = nthreads;
            // nt值受容器大小影响
            if (nt > list.length - n) {
                nt = list.length - n;
            }
            // 这里即将本组中的线程对象放入容器中
            for (int i = 0; i < nt; i++) {
                // 只保存alive状态的
                if (threads[i].isAlive()) {
                    list[n++] = threads[i];
                }
            }
            // 如果递归的话,
            if (recurse) {
                // 子线程组的数量
                ngroupsSnapshot = ngroups;
                // 做一次拷贝
                if (groups != null) {
                    groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
                } else {
                    groupsSnapshot = null;
                }
            }
        }
        // 递归重复以上步骤
        if (recurse) {
            for (int i = 0 ; i < ngroupsSnapshot ; i++) {
                n = groupsSnapshot[i].enumerate(list, n, true);
            }
        }
        // 返回实际放入list中的线程对象数目
        return n;
    }

另外附上一个自己写的测试demo

package thread;

/**
 * @author LiFeng
 * @create 2019-11-04 上午 8:45
 * @describe
 */
public class TestThreadGroup {
	public static void main(String[] args) {
		Runnable target = new Runnable() {
			@Override
			public void run() {
				try {
					// 这里让线程休眠5s,避免线程执行完退出,保证main先执行完,不然结果可能不符合预期
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		// 不指定父线程组,则默认父线程组为当前线程组,即main线程组
		ThreadGroup mytg1 = new ThreadGroup("main-my-tg1");
		// 指定 mytg1 为父线程组
		ThreadGroup mytg2 = new ThreadGroup(mytg1, "main-my-tg1-tg2");

		// 该方法返回当前线程组所有子、孙线程组的总个数,注意,这是一个估计值,因为其内部结构可能会动态改变。该方法主要用于测试与监控
		int activeGroupCount = Thread.currentThread().getThreadGroup().activeGroupCount();

		// 初始化容器,预期容量同activeGroupCount
		ThreadGroup[] tgarr = new ThreadGroup[activeGroupCount];
		// 默认递归方式,取得所有子孙线程组
		int enumerate = Thread.currentThread().getThreadGroup().enumerate(tgarr);
		for (int i = 0; i < enumerate; i++) {
			System.out.println(tgarr[i].getName());
		}

		System.out.println("-------------------------------------");

		// 非递归方式
		ThreadGroup[] tgarr2 = new ThreadGroup[activeGroupCount];
		int enumerate2 = Thread.currentThread().getThreadGroup().enumerate(tgarr2, false);
		for (int i = 0; i < enumerate2; i++) {
			System.out.println(tgarr2[i].getName());
		}

		System.out.println("-------------------------------------");

		Thread a = new Thread(target, "main-a");
		Thread b = new Thread(mytg1, target, "main-mytg1-b");
		Thread c = new Thread(mytg2, target, "main-mytg1-mytg2-c");

		// 注意,这里必须启动才算真正加入线程组中
		a.start();
		b.start();
		c.start();

		// 类似上面的activeGroupCount方法,不介绍了
		int activeCount = Thread.currentThread().getThreadGroup().activeCount();

		Thread[] tarr = new Thread[activeCount];
		int enumerate3 = Thread.currentThread().getThreadGroup().enumerate(tarr);
		for (int i = 0; i < enumerate3; i++) {
			System.out.println(tarr[i].getName());
		}

		System.out.println("-------------------------------------");

		Thread[] tarr2 = new Thread[activeCount];
		int enumerate4 = Thread.currentThread().getThreadGroup().enumerate(tarr2, false);
		for (int i = 0; i < enumerate4; i++) {
			System.out.println(tarr2[i].getName());
		}


		System.out.println();

	}
}

输出结果如下:

结果是符合预期的,只是多了一些额外的东西~~,这个Monitor Ctrl-Break 线程是跟随main线程一起运行起来的,具体的不了解,不做深究。自行Google。

好了,我暂时真的不想在这个东西上花太多时间,有机会再深入。

### JMeter 线程组的配置与使用方法 JMeter 的线程组是性能测试的核心组件之一,它定义了如何模拟用户负载以及请求发送的方式。以下是关于 JMeter 线程组配置和使用的详细介绍: #### 1. 基本概念 JMeter 线程组是一个测试计划的基础单元,所有其他元件都需要嵌套在至少一个线程组中运行。每个线程代表一个虚拟用户,这些线程可以并行执行任务[^1]。 #### 2. 主要参数说明 以下是一些常见的线程组参数及其作用: - **Number of Threads (users)**:表示需要模拟的用户数量,即并发线程的数量。 - **Ramp-Up Period (in seconds)**:指启动全部线程所需的时间间隔(以秒为单位)。例如,如果有 10 个线程,并且 Ramp-Up 时间设为 10 秒,则每秒钟会启动一个新的线程[^3]。 - **Loop Count**:控制每个线程重复执行采样器操作的次数。如果设置为无限循环 (`Forever`) 或者勾选 `Scheduler` 并设定结束时间,则可以根据需求灵活调整测试持续周期[^2]。 #### 3. 进阶功能——自定义线程组 为了更精确地控制流量模式,可以通过安装插件扩展标准线程组的功能。比如 Custom Thread Groups 提供多种预定义模板来实现复杂的业务逻辑仿真,像阶梯型增长、脉冲波形等特殊场景下的压力施加方式都可以轻松完成配置。 #### 4. 同步定时器的应用 当涉及到某些特定情况下需让多个请求同时发生时,可利用 Synchronizing Timer 来协调不同线程之间的行为动作。需要注意的是,在实际应用过程中应合理规划其相关属性值以免造成不必要的延迟或者资源浪费现象出现。例如,“超时时间”的计算公式可以帮助确定合适的等待上限[^4]: \[ \text{超时时间} > (\text{请求集合数量} * 1000) / (\text{线程数} / \text{线程加载时间}) \] ```python # 示例 Python 计算脚本用于估算同步定时器的最佳超时时间 def calculate_timeout(requests, threads, ramp_up): thread_load_time = ramp_up / threads timeout_ms = requests * 1000 / (threads / thread_load_time) return int(timeout_ms) requests_count = 50 thread_number = 100 rampup_period_seconds = 60 optimal_timeout = calculate_timeout(requests_count, thread_number, rampup_period_seconds) print(f"Optimal Timeout Value: {optimal_timeout} ms") ``` 以上代码片段展示了如何依据给定条件动态得出推荐的同步定时器超时数值。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值