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

Java多线程分数增减作业求助:实现线程安全的Runnable方案

Fixing Your Thread-Safe Score Updater Program

Hey there! Let's get your thread-safe score updater working properly. Your core goal is clear: two Score objects, 20 total threads (5 increment + 5 decrement per score), all using Runnable and thread-safe operations. Let's break down what's missing in your current code, then walk through the corrected version.

What's Off in Your Current Implementation

  • Your ScoreRunnerDemo doesn't connect to any Score instance — it has its own score field which isn't what you need. Each thread should operate on one of the two shared Score objects.
  • There's no logic for incrementing or decrementing the score; the run() method just prints a counter.
  • The main method has invalid code (like ScoreRunnerDemo.getScore which doesn't exist, and ScoreRunner() which isn't a valid call) and doesn't properly create/start threads.
  • You haven't differentiated between increment and decrement threads — each thread needs to know whether to add or subtract from the score.

Corrected Code

First, your Score class is actually already thread-safe thanks to the synchronized modifier on updateScore — we don't need to change that. Let's fix the rest:

Runnable Class (ScoreUpdater)

This class will handle modifying a specific Score instance with a given change amount (positive for increment, negative for decrement):

class ScoreUpdater implements Runnable {
    private final Score targetScore;
    private final double changeAmount;

    // Constructor to pass in the Score to modify and the change value
    public ScoreUpdater(Score targetScore, double changeAmount) {
        this.targetScore = targetScore;
        this.changeAmount = changeAmount;
    }

    @Override
    public void run() {
        try {
            // Each thread performs 5 updates (matches your original loop intent)
            for (int i = 0; i < 5; i++) {
                targetScore.updateScore(changeAmount);
                Thread.sleep(100); // Simulate work between updates
            }
        } catch (InterruptedException e) {
            System.out.printf("Thread updating Score ID %d was interrupted%n", targetScore.getId());
            Thread.currentThread().interrupt(); // Preserve interrupt status for cleanup
        }
        System.out.printf("Finished updating Score ID %d with change %.2f%n", targetScore.getId(), changeAmount);
    }
}

Main Class (ScoreRunner)

This creates the two Score objects, sets up all 20 threads, starts them, and waits for completion:

public class ScoreRunner {
    public static void main(String[] args) {
        // Create two Score objects with unique IDs and initial score 100
        Score score1 = new Score(1, 100.0);
        Score score2 = new Score(2, 100.0);

        // Array to hold all 20 threads for easy management
        Thread[] threads = new Thread[20];
        int threadIndex = 0;

        // 5 increment threads for Score 1 (+1.0 per update)
        for (int i = 0; i < 5; i++) {
            threads[threadIndex++] = new Thread(new ScoreUpdater(score1, 1.0), "Score1-Inc-" + (i+1));
        }
        // 5 decrement threads for Score 1 (-1.0 per update)
        for (int i = 0; i < 5; i++) {
            threads[threadIndex++] = new Thread(new ScoreUpdater(score1, -1.0), "Score1-Dec-" + (i+1));
        }
        // 5 increment threads for Score 2 (+1.0 per update)
        for (int i = 0; i < 5; i++) {
            threads[threadIndex++] = new Thread(new ScoreUpdater(score2, 1.0), "Score2-Inc-" + (i+1));
        }
        // 5 decrement threads for Score 2 (-1.0 per update)
        for (int i = 0; i < 5; i++) {
            threads[threadIndex++] = new Thread(new ScoreUpdater(score2, -1.0), "Score2-Dec-" + (i+1));
        }

        // Start all threads
        for (Thread t : threads) {
            t.start();
        }

        // Wait for all threads to finish before printing final scores (good practice)
        try {
            for (Thread t : threads) {
                t.join();
            }
        } catch (InterruptedException e) {
            System.out.println("Main thread interrupted while waiting for worker threads");
        }

        // Print final state of both Score objects
        System.out.println("\nFinal Scores:");
        System.out.println("Score ID " + score1.getId() + ": " + score1.getScore());
        System.out.println("Score ID " + score2.getId() + ": " + score2.getScore());
    }
}

Key Explanations

  • Thread Safety: Your Score.updateScore method uses synchronized, which ensures only one thread can execute that method at a time for a given Score instance. This eliminates race conditions where multiple threads try to modify the score simultaneously.
  • Flexible Runnable: ScoreUpdater is designed to work with any Score and any change amount — you could easily adjust the number of updates or the change value without rewriting the whole class.
  • Thread Management: Using an array to hold threads makes it easy to start and join all of them. Calling join() ensures the main thread waits for all worker threads to finish before printing the final scores, so you get accurate results.
  • Debugging: We named each thread (e.g., "Score1-Inc-3") to make it easier to track which thread is doing what if you need to debug.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:12:38