You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java线程打印多余行问题:最后线程重复输出唤醒信息

Java线程重复打印唤醒信息的问题分析与解决

问题现象

运行一个包含线程的Java程序,逻辑是让线程随机休眠一段时间后打印唤醒信息。程序执行到末尾时,最后一个线程的“is NOW AWAKE”信息被重复打印6次,其余线程均正常打印一次休眠和唤醒信息。

相关代码

sampleThread.java

import java.util.Random;

public class sampleThread extends Thread{
    sampleThread thread;
    Random rand = new Random();

    public void run() {
        thread = new sampleThread();
        int randSleep = rand.nextInt(1000);

        System.out.println(thread.getName() + " is sleeping for " + randSleep + " milliseconds");

        try {
            Thread.sleep(randSleep);
            System.out.println(thread.getName() + " is NOW AWAKE");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

driver.java

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class driver {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        List<Future<?>> futArray = new ArrayList<>();
        ExecutorService es = Executors.newFixedThreadPool(6);

        sampleThread temp = new sampleThread();
        for (int i=0; i<120; i++) {
            Future<?> future = es.submit(temp);
            futArray.add(future);
        }
    }
}

异常输出

Thread-117 is sleeping for 547 milliseconds
Thread-117 is NOW AWAKE
Thread-118 is sleeping for 442 milliseconds
Thread-118 is NOW AWAKE
Thread-119 is sleeping for 182 milliseconds
Thread-119 is NOW AWAKE
Thread-120 is sleeping for 487 milliseconds
Thread-120 is NOW AWAKE
Thread-120 is NOW AWAKE
Thread-120 is NOW AWAKE
Thread-120 is NOW AWAKE
Thread-120 is NOW AWAKE
Thread-120 is NOW AWAKE

原因分析

核心问题在于线程安全与变量作用域:

  1. 代码仅创建了一个sampleThread实例temp,并将其重复提交给线程池120次。线程池的6个工作线程会并发调用这个实例的run方法。
  2. sampleThread类中的thread是实例级成员变量,属于共享资源。当多个工作线程同时执行run方法时,会不断覆盖该变量的引用,最终所有线程的thread都会指向最后一次创建的sampleThread实例(即Thread-120)。
  3. 当各个线程休眠结束后,打印的都是共享变量thread的名称,因此出现了Thread-120的唤醒信息被重复打印6次(对应线程池的6个工作线程)的现象。

解决方案

将sampleThread类中的成员变量thread移至run方法内部,改为局部变量。这样每个线程执行run方法时,都会拥有独立的thread变量,不会相互干扰。

修改后的sampleThread.java代码:

import java.util.Random;

public class sampleThread extends Thread{
    Random rand = new Random();

    public void run() {
        // 将thread改为run方法内的局部变量
        sampleThread thread = new sampleThread();
        int randSleep = rand.nextInt(1000);

        System.out.println(thread.getName() + " is sleeping for " + randSleep + " milliseconds");

        try {
            Thread.sleep(randSleep);
            System.out.println(thread.getName() + " is NOW AWAKE");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

验证结果

修改后,每个线程的休眠和唤醒信息都会仅打印一次,不再出现重复输出的异常情况。

内容的提问来源于stack exchange,提问作者suttertub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 11:30:50