Java中两个线程访问共享变量
我正在用 Java 构建一个应用程序,它需要从两个类的实例访问哈希表,并且两个类都扩展线程。我已在两个类之一中声明了哈希表。当我尝试从其中一个类访问哈希表内容时,我总是得到 null。另一个类能够毫无问题地访问内容。我以为这是并发控制的问题。由于这些是不同类的线程,我们不能使用同步方法。有没有办法使哈希表可以从两个类的线程访问?
这是我的应用程序代码的一些部分 这是存储 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);
}
}
}
访问“ChatWindows”HashMap 的两个类
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");
}
}
} }
I'm building an application in Java which requires a Hashtable to be accessed from instances of two classes and both extend threads. I have declared the Hashtable in one of the two classes. I always get null when i try to access the Hashtable contents from one of the classes. The other class is able to access the contents without any problem. I thought this was a problem of concurrency control. Since these are threads of different classes we cannot use synchronized methods. Is there a way to make the Hashtable accessible from threads of both the classes?
Here are the some parts of the code of my application
This is the class which stores the 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);
}
}
}
Two classes which access 'ChatWindows' HashMap
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,"");
}
This class has run() method too, but that doesn't use the HashMap. This class is able to access the 'ChatWindows' properly.'ChatListenThread' class is not able to access the contents of HashMap properly.
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");
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是有可能的。查看在两个线程之间安全共享数据。
It's possible. Take a look at Sharing data safely between two threads.
好吧,我无法使用你的代码,因为我不明白,我看到的是你想要这样的东西:
JTabbedPane
创建一个空的JFrame
并启动一个连接到Socket
的线程。ChatPanel
(~JTextArea
) 并将其添加到选项卡之一ChatPanel
添加到处理来自“from
”的消息ChatPanel
所以我这样做了,并发布了下面的代码! 希望您能使用它!
如果您想测试一下,请首先启动
TestChatServer
(代码如下),然后启动ChatSupervisor
.这是客户端的代码
这是测试服务器的代码:
Okey, I couldn't use your code because I don't understand, what I did see was that you want something like this:
JFrame
with aJTabbedPane
and start a thread that connects to aSocket
ChatPanel
(~JTextArea
) and add it to one of the tabsChatPanel
to aMap
that handles the messages from "from
"ChatPanel
So I did that and I'm posting the code below! Hope that you can use it!
If you like to test this, first start the
TestChatServer
(code below) and then theChatSupervisor
.This is the code for the client
This is the code for the test server: