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; } }
关键说明
- 共享实例:通过构造函数将同一个
ClickerMemory实例传给所有Clicker线程,确保所有线程操作的是同一个内存数组。 - 线程安全:使用
synchronized (CM)对读写内存数组和索引的代码块加锁,避免多线程同时操作导致的数据覆盖或索引混乱。 - 统一管理:去掉了原来的全局静态
index,改用ClickerMemory中的实例变量index,统一管理内存索引。
内容的提问来源于stack exchange,提问作者Hero586
相关产品推荐
相关产品推荐

