2011-11-09 60 views
2

我有一個ArrayList需要從我的GUI的多個組件讀取和寫入。我在下面這個簡潔的代碼段中大幅減少了代碼量來說明問題。如何同步對多線程訪問的數組列表的訪問?

父框架可能有許多內部框架,每個內部框架都需要它自己的此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); 
    } 
} 

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); 
} 
} 

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; 
    } 
} 
+3

不要* if(s ==「Tab1」)*,請使用* .equals()*。 – JimmyB

+0

@HannoBinder +1它在這裏只能正常工作,因爲字符串文字是被執行的 –

回答

1

通過沿構造ArrayList中(並使其成爲場)

public class ParentFrame extends JFrame{ 
    private static final long serialVersionUID = 1L; 
    JLayeredPane desktop; 
    JInternalFrame internalFrame; 
    private List<Integer> myArrayList; 

    public ParentFrame() { 
     super("parent frame"); 
     myArrayList= new ArrayList<Integer>(); 
     myArrayList.add(8); 
     myArrayList.add(6); 
     myArrayList.add(7); 
     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); 




     desktop.add(internalFrame); 
     internalFrame.pack(); 
     internalFrame.setSize(new Dimension(ifWidth,ifHeight)); 
     internalFrame.setVisible(true); 
    } 


    private void createTab(JTabbedPane jtp, String s) { 
     if(s=="Tab1"){ 
      TestGUI myTimeSeriesGUI = new TestGUI(myArrayList); 
      jtp.add(s,myTimeSeriesGUI); 
     } 
     else{jtp.add(s, new JLabel("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); 
} 

和パ

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); 
} 
+0

+1給我舉個例子。我想我已經在我的實際應用中這樣做了,但你的代碼讓我明白了。在我回復這篇文章之前,我會稍微處理一下我的代碼。 – CodeMed

1

你需要傳遞給全球的列表的引用(或封裝該全局列表的對象)到每個組件。在他們的構造函數傳遞是去最簡單的方法:

ParentFrame.java:

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); 
     ... 

TestGUI.java:

private List<Integer> list; 
TestGUI(List<Integer> list) { 
    this.list = list; 
    ... 
+0

謝謝。但是,你能給我一個例子,我的代碼。或者可能是一篇文章的鏈接。我很難確切地知道你的意思。 – CodeMed

+0

+1。謝謝。我將在進一步回覆這篇文章之前檢查一下我的實際代碼。 – CodeMed

1

你需要使用一個控制器來維護這些類型的資源。對於Java UI,您可以使用您可以隨時通過單例方法訪問的控制器。這應該充當您的應用程序的交通警察。

+0

謝謝。你介意告訴我如何修改我的代碼來完成這個任務嗎?我發佈這篇文章是因爲我一直在研究它,並且需要更具體的東西。鏈接到一篇文章也將不勝感激。 – CodeMed

+0

+1給我看的東西。 – CodeMed

+0

如果你想要1,000篇文章,請查看MVC和singleton。 MVC是一個好主意,但實現起來總是一團糟,因爲當你考慮它時,用戶界面就是違反封裝的最好例子,因爲它的整個目標是展示你的模型的內部,讓世界看到。 所以我會在你的位置做主要實例化控制器使用你的工廠方法,然後讓控制爲你建立你的屏幕。超越屏幕本身的任何狀態信息只應發送給控制器,控制器將發送數據 – Thom

1

你可以使用Service Locator模式(這也可能幫助你堅持磁盤的要求)。

喜歡的東西

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

    public static IArrayHandler getArrayHandler() { 
    return handler; 
    } 

} 

然後你就可以創建你ArrayHandler處理創建和跟蹤您的陣列。

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

這樣,你不需要,當你需要「沒有更多的變量」以繞過參數和變化的方法或構造函數簽名:那麼在你的代碼,你可以用像讓你的陣列。無論如何,這是一種我喜歡和感覺舒服的模式。因人而異。乾杯。

+0

謝謝。 +1爲我提供了另一種研究方法。 – CodeMed