同步列表中的线程

时间:2014-02-14 20:11:20

标签: java multithreading sockets client-server

我知道处理线程同步有很多问题但是没有人给我解释我如何在我的实现中使用它。所以我有一个服务器等待客户端连接,因为在连接时为每个连接的客户端创建一个线程,每个客户端发送的每个消息都将显示在服务器上,客户端IP>>然后,每个客户端将从服务器检索此消息,以便每个客户端具有相同的消息。与mIRC类似,可以添加..

好的,问题是:

我保留了一个在链接列表中连接的每个客户端的会话实例。

我的会话课很简单:

public class Session extends Thread{
    private Socket soc;

    public BufferedReader in;
    public PrintWriter out;

    public Session(Socket in_client){
        //soc = new Socket();
        soc = in_client;
        this.start();
    }

    @Override
    public void run() {

        try{

            in = new BufferedReader(new InputStreamReader(soc.getInputStream()));
            out = new PrintWriter(soc.getOutputStream(), true);

            String inputLine;

            while(true){
                if((inputLine = in.readLine()) != null){
                    textArea.append("Client IP["+soc.getInetAddress()+"]: " + inputLine+"\n");

                    for(Session s:dstruct)
                        s.out.println(s.soc.getInetAddress()+">"+inputLine);
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }catch(IOException e ){
            try {
                in.close();
                out.close();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }}
    }

}

在服务器线程运行方法中,我创建会话并通过以下方式将它们推送到数据结构链表:

while(true){        
    if((clientSocket = serverSocket.accept())!=null){
        dstruct.push(new Session(clientSocket));
    }

现在我如何让这些线程同步?我读过许多不同的建议,比如 调用synchronized(...)或在方法声明中同步,也读取通知,但无法理解通知线程时实现的内容, 在这种情况下我会把它放在哪里? 我有一个服务器线程,用于将客户端连接到由Thread扩展的会话。主线程是否应该同步子线程,或者子线程是否应该以某种方式同步它们的som synchronized方法?

2 个答案:

答案 0 :(得分:0)

如果我正确理解了这个问题,您需要确保Sessiondstruct读取时,可以看到Sessions已放入的所有Server清单?最简单的方法是使用java.util.concurrent中的类,例如ConcurrentLinkedQueueConcurrentLinkedDeque

尝试将dstruct定义为ConcurrentLinkedQueue<Session>

答案 1 :(得分:0)

同步线程的目的是确保线程共享的任何数据的操作都是 atomically ,以确保线程看到的数据的一致性。在同步块或方法中同步的效果是进入该块的第一个线程将获取与同步对象关联的监视器上的锁。随后通过在同一对象上输入相同或另一个同步块/方法来请求锁定的所有其他线程将必须等到锁定被释放,这在初始线程退出同步块时发生。

在您的情况下,共享数据是LinkedList dstruct,这是您需要在所有操作上具有原子性的对象。因此,在您展示的代码中,您需要在两个位置进行同步:

在会话的run()方法中,您需要同步整个for循环:

synchronized(dstruct) {
  for (Session s: dstruct)
    s.out.println(s.soc.getInetAddress()+">"+inputLine);
  }
}

在服务器的run()方法中,围绕push()操作:

if ((clientSocket = serverSocket.accept()) != null) {
  synchronized(dstruct) {
    dstruct.push(new Session(clientSocket));
  }
}

通过谷歌搜索“java线程同步”,你会发现很多关于这个主题的材料和学习资源,比如this one。我很确定你会找到一些可以让你清楚的东西。