Java中实现Runnable接口定义任务逻辑,重写无参无返回值的run()方法,通过线程或线程池执行,解耦任务与执行机制。

Java 中通过实现 Runnable 接口编写多线程并发逻辑,核心是把任务逻辑封装进 run() 方法,再交由线程或线程池执行——它不直接创建线程,而是定义“要做什么”,解耦任务与执行机制。
实现 Runnable 接口的基本写法
只需重写 run() 方法,里面放你要并发执行的代码。注意:该方法无参数、无返回值、不抛受检异常。
例如:
public class PrintTask implements Runnable {
private final String message;
private final int times;
public PrintTask(String message, int times) {
this.message = message;
this.times = times;
}
@Override
public void run() {
for (int i = 0; i < times; i++) {
System.out.println(Thread.currentThread().getName() + ": " + message);
try {
Thread.sleep(100); // 模拟耗时操作
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
return;
}
}
}
}
启动线程的两种常用方式
方式一:手动 new Thread + start()
立即学习“Java免费学习笔记(深入)”;
- 适合简单、一次性任务
- 每个
Runnable实例可被多个线程复用(但要注意共享状态线程安全) - 示例:
new Thread(new PrintTask("Hello", 3)).start();
方式二:提交给 ExecutorService(推荐)
- 避免频繁创建/销毁线程,资源可控,支持调度、关闭、结果获取等
- 示例:
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(new PrintTask("Task-A", 2));
executor.submit(new PrintTask("Task-B", 2));
executor.shutdown(); // 启动有序关闭
处理共享数据时的线程安全要点
多个线程执行同一个 Runnable 实例(或访问相同对象字段)时,若涉及读写共享变量,必须同步:
- 用
synchronized块或方法保护临界区 - 优先使用
java.util.concurrent包下的线程安全类(如AtomicInteger、ConcurrentHashMap) - 避免在
run()中直接修改外部非线程安全对象(如普通ArrayList)
例如计数器场景,不要用 int count++,改用 AtomicInteger:
private final AtomicInteger counter = new AtomicInteger(0); // ... int current = counter.incrementAndGet();
如何获取任务执行结果(Runnable 本身不行,需变通)
Runnable 的 run() 没有返回值。若需结果,有以下选择:
- 用
Callable<T>替代(配合Future),但这就不是Runnable了 - 在
Runnable内部通过回调、队列、原子引用等方式“传出”结果 - 最常见做法:把结果写入线程安全容器(如
ConcurrentLinkedQueue或BlockingQueue),主线程后续消费
例如:
BlockingQueue<String> results = new LinkedBlockingQueue<>();
Runnable task = () -> {
String res = doSomeWork();
try {
results.put(res); // 安全入队
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};
executor.submit(task);
// 主线程 later:String r = results.poll();


















