直接继承Thread类无法控制并发数量,必须借助Semaphore或线程池等协调机制;推荐使用固定大小的ExecutorService调度任务,而非手动start()线程。

直接继承 Thread 类本身不提供内置的并发数量控制能力。它只是封装了一个线程执行单元,每次调用 start() 就会创建并启动一个新线程——这恰恰是容易导致并发失控的根源。所以,不能靠“继承 Thread 类”这一步来限制并发数;真正起作用的是后续引入的协调机制。
要实现限制并发数量,必须在 Thread 子类的运行逻辑中,配合外部资源协调工具或统一调度层。以下是两种切实可行、符合实际工程场景的做法:
使用 Semaphore 控制并发入口
适用于需要精确控制“同时运行的线程数”,且任务逻辑已封装在 Thread 子类中:
- 创建一个静态
Semaphore,设定许可数量(如 3); - 在
run()方法开头调用acquire(),阻塞直到获得许可; - 执行业务逻辑(比如模拟耗时操作);
- 最后在
finally块中调用release(),归还许可。
import java.util.concurrent.Semaphore;
class LimitedThread extends Thread {
private static final Semaphore semaphore = new Semaphore(3); // 最多3个并发
@Override
public void run() {
try {
semaphore.acquire(); // 等待许可
System.out.println(getName() + " 开始执行");
Thread.sleep(1000);
System.out.println(getName() + " 执行完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release(); // 释放许可
}
}
}
// 启动10个线程,但最多3个同时运行
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new LimitedThread().start();
}
}
}改用 Thread + 外部线程池调度(推荐)
更合理的方式是:把任务逻辑写成 Thread 子类(或 Runnable),但不直接 start(),而是提交给固定大小的线程池:
立即学习“Java免费学习笔记(深入)”;
-
LimitedThread仍可存在,只负责定义行为; - 实际启动交给
ExecutorService,由它决定何时、用哪个线程执行; - 这样既保留了自定义线程逻辑的灵活性,又把并发控制权交给成熟组件。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class LimitedThread extends Thread {
private final String taskName;
LimitedThread(String name) {
this.taskName = name;
}
@Override
public void run() {
System.out.println(taskName + " 开始(线程:" + Thread.currentThread().getName() + ")");
try { Thread.sleep(800); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
System.out.println(taskName + " 完成");
}
}
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(4); // 严格限制为4个并发
for (int i = 0; i < 12; i++) {
final int id = i;
pool.submit(() -> new LimitedThread("Task-" + id).run());
}
pool.shutdown();
}
}不推荐的做法:手动计数 + synchronized
例如用静态变量 runningCount 加锁增减——容易出错、难维护、无法应对中断和异常退出,且不具备公平性与阻塞等待能力,生产环境应避免。
本质上,并发数量控制属于资源协调问题,不是线程创建方式的问题。继承 Thread 是一种低层抽象,而限流、排队、复用等能力,应由 Semaphore、ExecutorService 或 ThreadPoolExecutor 这类高层工具承担。
不复杂但容易忽略:限制并发的关键不在“怎么建线程”,而在“谁来管它们一起跑”。


















