Java 如何同步对多线程访问的数组列表的访问?

Java 如何同步对多线程访问的数组列表的访问?,java,arraylist,add,Java,Arraylist,Add,我有一个需要从GUI的多个组件读取和写入的ArrayList。我已经大幅减少了代码量,试图在下面这个简明的代码段中说明这个问题 父帧可能有许多内部帧,每个内部帧都需要此ArrayList的自身实例。但是,特定内部框架的所有子组件都需要访问此ArrayList的同一实例,以便在特定内部框架的一个真实ArrayList中维护添加和删除。对于本例,ArrayList中的所有数据都需要在内存中。不过,稍后我将添加代码,以便在每次内存中发生更改时更新持久数据文件 这是我的简化代码段。有谁能告诉我如何更改此

我有一个需要从GUI的多个组件读取和写入的ArrayList。我已经大幅减少了代码量,试图在下面这个简明的代码段中说明这个问题

父帧可能有许多内部帧,每个内部帧都需要此ArrayList的自身实例。但是,特定内部框架的所有子组件都需要访问此ArrayList的同一实例,以便在特定内部框架的一个真实ArrayList中维护添加和删除。对于本例,ArrayList中的所有数据都需要在内存中。不过,稍后我将添加代码,以便在每次内存中发生更改时更新持久数据文件

这是我的简化代码段。有谁能告诉我如何更改此代码,使其能够为我提供所需的读/写访问权限?此外,任何相关文章的链接将不胜感激

ParentFrame.java:

package testGlobalArrayList;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Panel;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JTabbedPane;
import java.util.*;

public class ParentFrame extends JFrame{
private static final long serialVersionUID = 1L;
JLayeredPane desktop;
JInternalFrame internalFrame;

public ParentFrame() {
    super("parent frame");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setPreferredSize(new Dimension(600, 300));
    Panel p = new Panel();
    this.add(p, BorderLayout.SOUTH);
    desktop = new JDesktopPane();
    this.add(desktop, BorderLayout.CENTER);
    this.pack();
    this.setSize(new Dimension(600, 300));
    this.setLocationRelativeTo(null);
    final int DELTA = 40;
    int offset = DELTA;
        int ifWidth = 400;
        int ifHeight = 200;
        internalFrame = new JInternalFrame("internal frame", true, true, true, true);
        internalFrame.setLocation(offset, offset);
        offset += DELTA;

        JTabbedPane jtp = createTabbedPane();
        internalFrame.add(jtp);

        // want to make this ArrayList read/write accessible to every GUI component below this level            
        ArrayList<Integer> myArrayList= new ArrayList<Integer>();
        myArrayList.add(8);
        myArrayList.add(6);
        myArrayList.add(7);

        desktop.add(internalFrame);
        internalFrame.pack();
        internalFrame.setSize(new Dimension(ifWidth,ifHeight));
        internalFrame.setVisible(true);
    }
private JTabbedPane createTabbedPane() {
    JTabbedPane jtp = new JTabbedPane();
    jtp.setMinimumSize(new Dimension(600,300));
    createTab(jtp, "Tab1");
    createTab(jtp, "Tab2");
    return jtp;
    }
private void createTab(JTabbedPane jtp, String s) {
    if(s=="Tab1"){
        TestGUI myTimeSeriesGUI = new TestGUI();
        jtp.add(s,myTimeSeriesGUI);
    }
    else{jtp.add(s, new JLabel("TabbedPane " + s, JLabel.CENTER));}
    }
public static void main(String args[]) {
    ParentFrame myParentFrame = new ParentFrame();
    myParentFrame.setVisible(true);
    }
}
    List<Integer> myArrayList= new ArrayList<Integer>();
    myArrayList.add(8);
    myArrayList.add(6);
    myArrayList.add(7);

    JTabbedPane jtp = createTabbedPane(myArrayList);
    internalFrame.add(jtp);

...

private JTabbedPane createTabbedPane(List<Integer> list) {
    JTabbedPane jtp = new JTabbedPane();
    jtp.setMinimumSize(new Dimension(600,300));
    createTab(jtp, "Tab1", list);
    createTab(jtp, "Tab2", list);
    return jtp;
}
private void createTab(JTabbedPane jtp, String s, List<Integer> list) {
    if ("Tab1".equals(s)){
        TestGUI myTimeSeriesGUI = new TestGUI(list);
        ...
TestPanel.java:

package testGlobalArrayList;

import java.awt.Color;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

public class TestPanel extends JPanel {
public TestPanel (){
    this.setBackground(getRandomColor());
    this.setBorder( new EtchedBorder() );
    this.setSize(150,20);
}
void anotherMethod(){
    //want to be able to add or delete records from same ArrayList here
    myArrayList.remove(1);
    myArrayList.remove(2);
    myArrayList.remove(3);
}
    private static Color getRandomColor(){
    Random rand = new Random();
    float r = rand.nextFloat();
    float g = rand.nextFloat();
    float b = rand.nextFloat();
    Color randomColor = new Color(r, g, b);
        return randomColor;
    }
}

您需要将对全局列表(或封装此全局列表的对象)的引用传递给每个组件。将其传递给构造函数是最简单的方法:

ParentFrame.java:

package testGlobalArrayList;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Panel;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JTabbedPane;
import java.util.*;

public class ParentFrame extends JFrame{
private static final long serialVersionUID = 1L;
JLayeredPane desktop;
JInternalFrame internalFrame;

public ParentFrame() {
    super("parent frame");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setPreferredSize(new Dimension(600, 300));
    Panel p = new Panel();
    this.add(p, BorderLayout.SOUTH);
    desktop = new JDesktopPane();
    this.add(desktop, BorderLayout.CENTER);
    this.pack();
    this.setSize(new Dimension(600, 300));
    this.setLocationRelativeTo(null);
    final int DELTA = 40;
    int offset = DELTA;
        int ifWidth = 400;
        int ifHeight = 200;
        internalFrame = new JInternalFrame("internal frame", true, true, true, true);
        internalFrame.setLocation(offset, offset);
        offset += DELTA;

        JTabbedPane jtp = createTabbedPane();
        internalFrame.add(jtp);

        // want to make this ArrayList read/write accessible to every GUI component below this level            
        ArrayList<Integer> myArrayList= new ArrayList<Integer>();
        myArrayList.add(8);
        myArrayList.add(6);
        myArrayList.add(7);

        desktop.add(internalFrame);
        internalFrame.pack();
        internalFrame.setSize(new Dimension(ifWidth,ifHeight));
        internalFrame.setVisible(true);
    }
private JTabbedPane createTabbedPane() {
    JTabbedPane jtp = new JTabbedPane();
    jtp.setMinimumSize(new Dimension(600,300));
    createTab(jtp, "Tab1");
    createTab(jtp, "Tab2");
    return jtp;
    }
private void createTab(JTabbedPane jtp, String s) {
    if(s=="Tab1"){
        TestGUI myTimeSeriesGUI = new TestGUI();
        jtp.add(s,myTimeSeriesGUI);
    }
    else{jtp.add(s, new JLabel("TabbedPane " + s, JLabel.CENTER));}
    }
public static void main(String args[]) {
    ParentFrame myParentFrame = new ParentFrame();
    myParentFrame.setVisible(true);
    }
}
    List<Integer> myArrayList= new ArrayList<Integer>();
    myArrayList.add(8);
    myArrayList.add(6);
    myArrayList.add(7);

    JTabbedPane jtp = createTabbedPane(myArrayList);
    internalFrame.add(jtp);

...

private JTabbedPane createTabbedPane(List<Integer> list) {
    JTabbedPane jtp = new JTabbedPane();
    jtp.setMinimumSize(new Dimension(600,300));
    createTab(jtp, "Tab1", list);
    createTab(jtp, "Tab2", list);
    return jtp;
}
private void createTab(JTabbedPane jtp, String s, List<Integer> list) {
    if ("Tab1".equals(s)){
        TestGUI myTimeSeriesGUI = new TestGUI(list);
        ...
List myArrayList=new ArrayList();
myArrayList.add(8);
myArrayList.add(6);
myArrayList.add(7);
JTabbedPane jtp=createTabbedPane(myArrayList);
内部帧添加(jtp);
...
专用JTabbedPane createTabbedPane(列表){
JTabbedPane jtp=新JTabbedPane();
jtp.设置最小尺寸(新尺寸(600300));
createTab(jtp,“表1”,列表);
createTab(jtp,“表2”,列表);
返回jtp;
}
私有void createTab(JTabbedPane jtp,字符串s,列表){
如果(“表1”。等于){
TestGUI myTimeSeriesGUI=新的TestGUI(列表);
...
TestGUI.java:

package testGlobalArrayList;

import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.ArrayList;
import javax.swing.Box;

public class TestGUI extends JPanel{

TestGUI(){
    Box verticalBox = Box.createVerticalBox();
    verticalBox.add(new TestPanel());
    verticalBox.add(new TestPanel());
    verticalBox.add(new TestPanel());
    this.add(verticalBox, BorderLayout.CENTER);
}
void anotherMethod(){
    // want to be able to add or delete records to same ArrayList here
    myArrayList.add(5);
    myArrayList.add(3);
    myArrayList.add(0);
    myArrayList.add(9);
}
}
private List<Integer> list;
TestGUI(List<Integer> list) {
    this.list = list;
    ...
私有列表;
TestGUI(列表){
this.list=列表;
...

您需要使用控制器来维护这些类型的资源。对于java UI,您可以随时使用通过单例方法访问的控制器。这应该充当应用程序的交通警察。

在构造函数中传递arraylist(并将其设为字段)

公共类ParentFrame扩展了JFrame{
私有静态最终长serialVersionUID=1L;
JLayeredPane桌面;
内部框架;
私有列表myArrayList;
公共父框架(){
超级(“父帧”);
myArrayList=新建ArrayList();
myArrayList.add(8);
myArrayList.add(6);
myArrayList.add(7);
此.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
此.setPreferredSize(新尺寸(600300));
面板p=新面板();
添加(p,BorderLayout.SOUTH);
桌面=新的JDesktopPane();
添加(桌面、边框布局、中心);
这个包();
此.设置尺寸(新尺寸(600300));
此.setLocationRelativeTo(空);
最终积分增量=40;
整数偏移=增量;
int ifWidth=400;
int-ifHeight=200;
内部框架=新的内部框架(“内部框架”,真,真,真,真);
internalFrame.setLocation(偏移,偏移);
偏移量+=增量;
JTabbedPane jtp=createTabbedPane();
内部帧添加(jtp);
添加(内部框架);
internalFrame.pack();
internalFrame.setSize(新尺寸(ifWidth,ifHeight));
internalFrame.setVisible(true);
}
私有void createTab(JTabbedPane jtp,字符串s){
如果(s==“表1”){
TestGUI myTimeSeriesGUI=新的TestGUI(myArrayList);
jtp.add(s,myTimeSeriesGUI);
}
else{jtp.add(s,newjlabel(“TabbedPane”+s,JLabel.CENTER));}
}
}
TestGui成为

public class TestGUI extends JPanel{
private List<Integer> myArrayList;

TestGUI(List<Integer> myArrayList){
    Box verticalBox = Box.createVerticalBox();
    verticalBox.add(new TestPanel(myArrayList));
    verticalBox.add(new TestPanel(myArrayList));
    verticalBox.add(new TestPanel(myArrayList));
    this.add(verticalBox, BorderLayout.CENTER);
    this.myArrayList = myArrayList;
}
void anotherMethod(){
    // want to be able to add or delete records to same ArrayList here
    myArrayList.add(5);
    myArrayList.add(3);
    myArrayList.add(0);
    myArrayList.add(9);
}
公共类TestGUI扩展了JPanel{
私有列表myArrayList;
TestGUI(列出myArrayList){
Box verticalBox=Box.createVerticalBox();
add(新的测试面板(myArrayList));
add(新的测试面板(myArrayList));
add(新的测试面板(myArrayList));
此.add(垂直框,BorderLayout.CENTER);
this.myArrayList=myArrayList;
}
void-anotherMethod(){
//希望能够在此处向同一ArrayList添加或删除记录吗
myArrayList.add(5);
myArrayList.add(3);
myArrayList.add(0);
myArrayList.add(9);
}
和测试面板

public class TestPanel extends JPanel {
private ArrayList<Integer> myArrayList;
public TestPanel (ArrayList<Integer> myArrayList){
    this.setBackground(getRandomColor());
    this.setBorder( new EtchedBorder() );
    this.setSize(150,20);
    this.myArrayList = myArrayList;
}
void anotherMethod(){
    //want to be able to add or delete records from same ArrayList here
    myArrayList.remove(1);
    myArrayList.remove(2);
    myArrayList.remove(3);
}
公共类测试面板扩展了JPanel{
私人ArrayList myArrayList;
公共测试面板(ArrayList myArrayList){
这个.setBackground(getRandomColor());
此.setboorder(新的蚀刻边框());
这个。设置大小(150,20);
this.myArrayList=myArrayList;
}
void-anotherMethod(){
//想在此处添加或删除同一ArrayList中的记录吗
myArrayList.remove(1);
myArrayList.remove(2);
myArrayList.remove(3);
}

您可以使用服务定位器模式(这也可以帮助您满足持久化到磁盘的需求)

差不多

public ServiceLocator() {
  private static ArrayHandler handler=new ArrayHandler();

  public static IArrayHandler getArrayHandler() {
    return handler;
  }

}
然后,您可以创建ArrayHandler来处理数组的创建和跟踪。因此,在您的代码中,您可以通过以下方式获得数组:

ServiceLocator.getArrayHandler().getArray("myarray");

通过这种方式,当您需要“不再需要变量”时,您不需要传递参数和更改方法或构造函数签名。无论如何,这是一种我喜欢的模式,并且对.YMMV.Cheers感到满意。

如果(s==“Tab1”),请使用.equals()@HannoBinder+1它只能在这里正常工作,因为字符串文本是internetd谢谢。但是你能给我一个代码示例吗?或者是一篇文章的链接。我很难确切地知道你的意思。+1.谢谢。在进一步回复这篇文章之前,我会检查一下我的实际代码。谢谢。你愿意吗你介意告诉我如何修改我的代码来实现这一点吗?我发布这篇文章是因为我已经做了一段时间了,我需要一些更具体的东西。链接到一篇文章会更好