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

Java多线程如何共享同一ClickerMemory数组?

解决多线程共用ClickerMemory数组的问题

核心问题

你当前的Clicker类中,ClickerMemory CM = new ClickerMemory();是实例级变量,每个Clicker对象都会创建独立的ClickerMemory实例,自然无法共享数组。同时,全局静态变量static int index在多线程操作时会存在线程安全问题,建议将其移到ClickerMemory中统一管理。

解决方案:共享单一ClickerMemory实例

最直接的方式是让所有线程共用同一个ClickerMemory实例,同时处理多线程读写的同步问题,避免数据混乱。这里推荐构造函数注入共享实例的方式,低耦合且灵活。


修改后的代码

1. 调整Clicker类

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Robot;

public class Clicker extends Thread {
    // 改为引用共享的ClickerMemory实例,不再每个线程独立创建
    private final ClickerMemory CM;
    private final int Xcoord;
    private final int threadCount;

    // 构造函数传入全局共享的ClickerMemory实例
    Clicker(int a, int b, ClickerMemory sharedMemory) {
        Xcoord = a;
        threadCount = b;
        this.CM = sharedMemory;
    }

    public void run() {
        while (true) {
            try {
                Robot r = new Robot();
                for (int i = 0; i < 7; ++i) {
                    if (colorTrue(r, Xcoord)) {
                        // 对内存数组和索引的读写加同步锁,避免多线程冲突
                        synchronized (CM) {
                            if (CM.Memory[CM.index] == 0) {
                                CM.Memory[CM.index] = Xcoord;
                            }
                            CM.index++;
                        }
                        // 等待按钮变回红色
                        while (!whenIsRed(r, Xcoord)) {}
                        System.out.println("done");
                        break;
                    }
                }
                if (clockDetect(r)) {
                    Thread.sleep(200);
                    // 执行记忆点击时同步,避免读写冲突
                    synchronized (CM) {
                        CM.memoryModule(this.threadCount);
                        CM.index = 0;
                        // 重置内存数组(根据需求可选)
                        for (int i = 0; i < CM.Memory.length; i++) {
                            CM.Memory[i] = 0;
                        }
                    }
                    System.out.println("mem" + threadCount);
                }
            } catch (AWTException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static int nonNegativeCount(int num2) {
        return num2 - 1 < 0 ? 0 : num2;
    }

    static boolean clockDetect(Robot r) {
        Color a = r.getPixelColor(948, 540);
        return a.getBlue() == 172;
    }

    static boolean whenIsRed(Robot r, int X) {
        Color a = r.getPixelColor(X, 315);
        return a.getRed() == 255;
    }

    static boolean colorTrue(Robot r, int X) {
        Color a = r.getPixelColor(X, 315);
        return a.getGreen() == 255;
    }

    public static void main(String[] args) {
        // 创建一个全局共享的ClickerMemory实例
        ClickerMemory sharedMemory = new ClickerMemory();
        
        // 所有Clicker线程传入同一个共享实例
        Clicker c1 = new Clicker(800, 1, sharedMemory);
        Clicker c2 = new Clicker(850, 2, sharedMemory);
        Clicker c3 = new Clicker(900, 3, sharedMemory);
        Clicker c4 = new Clicker(960, 4, sharedMemory);
        Clicker c5 = new Clicker(1015, 5, sharedMemory);
        Clicker c6 = new Clicker(1070, 6, sharedMemory);
        Clicker c7 = new Clicker(1122, 7, sharedMemory);

        new Thread(c1).start();
        new Thread(c2).start();
        new Thread(c3).start();
        new Thread(c4).start();
        new Thread(c5).start();
        new Thread(c6).start();
        new Thread(c7).start();
    }
}

2. 调整ClickerMemory类

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;

public class ClickerMemory {
    public int[] Memory = new int[200];
    public int index = 0;
    private int num = 0;
    private int num2 = 0;

    @SuppressWarnings("deprecation")
    public void memoryModule(int tCount) throws InterruptedException {
        if (this.Memory[0] == 0) {
            return;
        }
        try {
            Robot R = new Robot();
            // 遍历内存时无修改操作,无需同步;若有其他线程可能修改,建议加锁
            for (int i = 0; i < Memory.length; ++i) {
                if (Memory[i] == 0) {
                    break;
                }
                if (i == 0 && Memory[1] != 0) {
                    i = 1;
                }
                Thread.sleep(500);
                R.mouseMove(this.Memory[i], 315);

                R.mousePress(InputEvent.BUTTON1_MASK);
                Thread.sleep(200);
                R.mouseRelease(InputEvent.BUTTON1_MASK);
                Thread.sleep(50);
                R.mouseMove(540, 360);

                System.out.println("Memory " + Memory[i] + "  " + i + " " + tCount);
                num = i;
            }
        } catch (AWTException e) {
            System.out.println("Mem Error" + Memory[1]);
        }
    }

    void editNum2() {
        this.num2 = this.num - 1 < 0 ? 0 : this.num - 1;
    }
}

关键说明

  1. 共享实例:通过构造函数将同一个ClickerMemory实例传给所有Clicker线程,确保所有线程操作的是同一个内存数组。
  2. 线程安全:使用synchronized (CM)对读写内存数组和索引的代码块加锁,避免多线程同时操作导致的数据覆盖或索引混乱。
  3. 统一管理:去掉了原来的全局静态index,改用ClickerMemory中的实例变量index,统一管理内存索引。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:52:09