线程池线程复用细节疑问:带构造参数的Runnable执行问题
Great question—this is a super common point of confusion when mixing thread pools with custom Runnable classes that have constructor parameters. Let's break this down step by step so you can see exactly what's going on.
1. Every MyRunnable Instance Has Its Own Independent Variables
First, let's clarify the critical distinction here: thread pools reuse threads, not your Runnable instances.
When you call executor.execute(new MyRunnable(a)), you’re creating a brand-new instance of MyRunnable every single time. The constructor parameter a gets assigned to that specific instance’s this.a member variable—this value is tied to the Runnable instance, not the thread that will eventually run it.
Here’s a concrete example to illustrate:
class MyRunnable implements Runnable { private int a; public MyRunnable(int a) { this.a = a; System.out.println("Created MyRunnable instance with a = " + a); } @Override public void run() { String threadName = Thread.currentThread().getName(); System.out.printf("Thread %s running with a = %d%n", threadName, a); } } // Usage public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); executor.execute(new MyRunnable(1)); executor.execute(new MyRunnable(2)); executor.execute(new MyRunnable(3)); executor.shutdown(); }
Sample output might look like this (note reused thread names but unique a values):
Created MyRunnable instance with a = 1
Created MyRunnable instance with a = 2
Created MyRunnable instance with a = 3
Thread pool-1-thread-1 running with a = 1
Thread pool-1-thread-2 running with a = 2
Thread pool-1-thread-1 running with a = 3
Even though the same thread runs the first and third tasks, each task uses its own a value from its own MyRunnable instance.
2. Watch Out for Shared External Objects
The only time you’ll run into variable issues is if your MyRunnable references a mutable external object shared across multiple instances. For example:
// A shared mutable list List<Integer> sharedList = new ArrayList<>(); executor.execute(new MyRunnable(1, sharedList)); executor.execute(new MyRunnable(2, sharedList));
Here, both MyRunnable instances operate on the same sharedList. If the run() method modifies this list without proper synchronization (like synchronized blocks or a thread-safe collection such as CopyOnWriteArrayList), you could get race conditions, missing data, or inconsistent state.
This is a standard thread safety issue, not something caused by thread pool reuse.
3. Thread Reuse Doesn’t Affect Your Runnable’s Variables
Thread pool threads might retain their own state (like ThreadLocal values) between tasks if you don’t explicitly clean them up. But this is separate from your MyRunnable instance’s variables.
Once a thread finishes executing your MyRunnable, that instance is eligible for garbage collection (unless another part of your code holds a reference to it). The thread itself just waits for the next task—no part of your Runnable’s state sticks around in the thread.
Key Takeaway
Your parameterized MyRunnable instances are completely independent of each other. Thread pool reuse only affects the threads that execute tasks, not the state stored in each task instance. As long as you’re not sharing mutable external objects across tasks, your a values will stay isolated and correct for each run.
内容的提问来源于stack exchange,提问作者murksiuke

