Доступ к общим переменным из двух потоков в Java - PullRequest
1 голос
/ 14 декабря 2010

Я создаю приложение на Java, для которого требуется доступ к Hashtable из экземпляров двух классов и обоих расширенных потоков.Я объявил Hashtable в одном из двух классов.Я всегда получаю нулевое значение, когда пытаюсь получить доступ к содержимому Hashtable из одного из классов.Другой класс может получить доступ к содержимому без каких-либо проблем.Я думал, что это проблема контроля параллелизма.Поскольку это потоки разных классов, мы не можем использовать синхронизированные методы.Есть ли способ сделать Hashtable доступным из потоков обоих классов?

Вот некоторые части кода моего приложения. Этот класс хранит HashMap:

public class DataStore {
public Map ChatWindows ;
public DataStore()
{
    ChatWindows = new ConcurrentHashMap();
}
public synchronized void putWindow(String with,ChatWindow t)
{
    ChatWindows.put(with,t);
    notifyAll();
}
public synchronized ChatWindow getWindow(String with)
{
    notifyAll();
    return (ChatWindow)ChatWindows.get(with);
}
public synchronized void ChatWindowOpen(chatClient cc,String with,String msg)
    {
       //    chatWith = with;
        ChatWindow t;
        System.out.println(with);
            t = getWindow(with);
           if(t == null)
           {
               t = new ChatWindow(cc,with,msg);
         //      th = new Thread(t);
               putWindow(with, t);
         //      th.start();
           }
           else
           {
              t.setVisible(true);

            }
}
}

Два класса, которые обращаются к HashMap ChatWindows

public class chatClient extends javax.swing.JFrame implements 

Runnable,ListSelectionListener,MouseListener,WindowListener{

  static String LoginName,chatWith,msgToChatWindow;
    Thread listThread=null,th,chatListen;
static  Socket soc;
static  DataOutputStream dout,dout1;
static  DataInputStream din,din1;
        DefaultListModel listModel;

        ChatWindow t;

    public DataStore ds;
/** Creates new form chatClient */
public chatClient(Login l,DataStore ds) {
    listModel = new DefaultListModel();
    initComponents();
    clientList.addListSelectionListener(this);

     clientList.addMouseListener(this);
     addWindowListener(this);
      this.LoginName=l.loginName;

        soc = l.soc2;
        din = l.din2;
        dout = l.dout2;
        dout1 = l.dout1;
        din1 = l.din1;
        super.setTitle(LoginName);

        listThread = new Thread(this);
        listThread.start();
        this.ds = ds;

}
.
.
.
.
public void mouseClicked(MouseEvent e)
{
    chatWith = (String)clientList.getSelectedValue();
    ds.ChatWindowOpen(this,chatWith,"");
}

В этом классе также есть метод run (), но он не использует HashMap.Этот класс может правильно обращаться к «ChatWindows». Класс «ChatListenThread» не может правильно обращаться к содержимому HashMap.

public class ChatListenThread implements Runnable{

DataOutputStream dout1;
DataInputStream din1;
public static chatClient cc;
public static ChatWindow t;
public DataStore ds;
    public ChatListenThread(Login l,DataStore ds)
    {
        din1 = l.din1;
        dout1= l.dout1;
        this.ds = ds;
    }
.
.
.
.
public void run(){
   while(true)
   {
       try{
                    String msgFromServer=new String();
                    msgFromServer = din1.readUTF();
                    StringTokenizer st=new StringTokenizer(msgFromServer);
        String msgFrom=st.nextToken();
        String MsgType=st.nextToken();
                    String msg = "";
                   while(st.hasMoreTokens())
        {
            msg=msg+" " +st.nextToken();
        }

                    ds.ChatWindowOpen(cc,msgFrom,msg);                       

       }
       catch(IOException e)
       {
            System.out.println("Read failed");

       }
   }

}}

Ответы [ 2 ]

2 голосов
/ 14 декабря 2010
1 голос
/ 14 декабря 2010

Окей, я не мог использовать твой код, потому что я не понимаю, что я видел, что ты хотел что-то вроде этого:

Screen shot

  1. Создайте пустой JFrame с JTabbedPane и запустите поток, который подключается к Socket
  2. Когда ввод поступает в сокет, создайте ChatPanel (~ JTextArea) и добавьте его на одну из вкладок
  3. Добавьте ChatPanel к Map, который обрабатывает сообщения от "from"
  4. Передать сообщение вновь созданному ChatPanel

Итак, я сделал это, и я публикую код ниже! Надеюсь, что вы можете использовать его!

Если вы хотите проверить это, сначала запустите TestChatServer (код ниже), а затем ChatSupervisor.

Это код для клиента

public class ChatSupervisor extends JFrame implements Runnable {

    JTabbedPane tabs = new JTabbedPane();
    Map<String, ChatPanel> chats = new ConcurrentHashMap<String, ChatPanel>();

    public ChatSupervisor() {
        super("Test Chat");
        add(tabs, BorderLayout.CENTER);

        new Thread(this).start();
    }

    public void run() {
        Socket sock = null;
        try {
            sock = new Socket("localhost", 32134);

            Scanner s = new Scanner(sock.getInputStream());
            while (true) {

                String from = s.next();
                String type = s.next();
                String message = s.nextLine();

                getChat(from).incomingMessage(type, message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sock != null) try { sock.close(); } catch (IOException e) {}
        }
    }

    public ChatPanel getChat(String from) {
        if (!chats.containsKey(from))
            chats.put(from, new ChatPanel(from));

        return chats.get(from);
    }

    public static void main(String[] args) {
        ChatSupervisor cs = new ChatSupervisor();
        cs.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cs.setSize(400, 300);
        cs.setVisible(true);
    }

    class ChatPanel extends JTextArea {
        public ChatPanel(final String from) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    tabs.addTab(from, ChatPanel.this);
                }
            });
        }
        public void incomingMessage(final String type, final String message) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    append("[" + type + "]" + message);
                    append("\n");
                }
            });
        }
    }
}

Это код для тестового сервера:

public class TestChatServer {
    public static void main(String[] args) throws Exception {
        Socket s = new ServerSocket(32134).accept();
        System.out.println("connected");
        PrintWriter p = new PrintWriter(s.getOutputStream());
        while (true) {

            p.println("hello info Hello World!");
            p.flush();
            Thread.sleep(1000);

            for (int i = 0; i < 10; i++) {
                p.println("test" + i + " warn Testing for testing " + i);
                p.flush();
                Thread.sleep(100);
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...