2014-11-02 3 views
-2

код ->http://pastebin.com/1PFCGWQyИспользование Синхронное коллекции между потоками

Блоки, которые у меня возникли проблемы с

class ClientSender implements Runnable { 
     Socket server; 
     ServerClientFrontEnd SCFE; 
     public ClientSender(Socket server, ServerClientFrontEnd SCFE){ 
      this.server = server; 
      this.SCFE = SCFE; 
     } 

     public void run(){ 
      try(ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream())){ 
       //System.out.println("Client chat ver. 0.1"); 
       //Scanner get = new Scanner(System.in); 
       while(!server.isClosed()){ 
        //System.out.print("YOU:"); 
        if(!SCFE.synchronizedOutputCollection.isEmpty()) // Here 
        { 
         logger.info("Has made it to ClientSender!"); 
         String string = SCFE.synchronizedOutputCollection.firstElement(); 
         logger.info(string); 
         out.writeObject(string); // Here 
         logger.info("Output Queue: " + SCFE.synchronizedOutputCollection.toString()); 
        } 
        //else{ logger.info("It failed the conditional"); } 
       } 
      } catch (IOException ex) { 
       //logger.info("Closing connection..."); 
       //System.exit(0); 
      } 
     } 
    } 
    class ClientReceiver implements Runnable { 
     Socket server; 
     ServerClientFrontEnd SCFE; 
     public ClientReceiver(Socket server, ServerClientFrontEnd SCFE){ 
      this.server = server; 
      this.SCFE = SCFE; 
     } 

     public void run(){ 
      try(ObjectInputStream in = new ObjectInputStream(server.getInputStream())){ 
       while(!server.isClosed()){ 
        SCFE.ChatBox.setText(SCFE.ChatBox.getText() + "\nOTHER: " + (String) in.readObject()); //Here 
        logger.info("Receiver has read object!"); 
       } 
       } catch (IOException ex) { 
        logger.info("Closing connection"); 
        System.exit(0); 
       } catch (ClassNotFoundException ex) { 
        Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 

По некоторым причинам, я не могу получить эту работу. Я уже работал над средой командной строки, но я хотел перенести ее в графический интерфейс пользователя, и эта проблема заставила меня сосредоточиться на более чем час. Я не знал, как обрабатывать тот факт, что оригинальный класс клиента вызвал другие потоки, которые мне нужно было отправлять и получать информацию на сервер и с сервера.

В принципе, моя программа работает, когда клиент подключается к серверу через ServerSocket, который THEN обрабатывает каждый запрос. Конечно, я недавно узнал о сокетах в четверг, но я хотел сделать свою собственную программу ... в любом случае, перейдя, проблема связана с классом ServerClientFrontEnd, который по какой-то причине и я не знаю как для жизни меня коллекция, которую я использую, чтобы получить введенный текст, либо остается пустой, либо просто не будет читать ее.

Возможно, это может иметь отношение к моей петле while, но она отлично работала раньше. У меня есть TON регистраторов повсюду, чтобы регистрировать все, и если я добавлю инструкцию else, когда он проверяет, является ли коллекция пустой, она определенно активирует инструкцию else повторно, ДАЖЕ ПОСЛЕ того, как synchronizedOutputCollection получает значение. Фактически, я даже печатаю значение внутри коллекции при нажатии кнопки отправки. Фактически, когда я пытаюсь использовать аналогичный оператор печати внутри потока, коллекция пуста и остается пустой.

Как я могу поделиться синхронизированной коллекцией объектов между потоками? Этот вопрос преследует меня, и я был бы очень признателен за ответ.

Также это можно запустить, вам просто нужно активировать сервер и 2 клиента, чтобы проверить его. P.S Я попытался BlockingQueues, но они заставляют поток GUI замерзать, потому что очередь никогда не читается, вызывая тупик.

+1

Хм, нет. Создайте [MCVE] (http://stackoverflow.com/help/mcve) (иначе известный как [SSCCE] (http://sscce.org/)) и вставьте его здесь. Не собирайтесь пробираться сквозь весь ваш проект, ища логическую ошибку. – markspace

+0

Я добавил блок кода для двух рассматриваемых потоков. У меня возникла проблема с добавленными комментариями, кроме областей интересов, где возникает проблема. Я не думаю, что могу сделать SSCCE, потому что это просто не сработает, и я не знаю, как заставить его работать, даже если я обрезал код. –

+0

«Я не могу заставить это работать» не является описанием проблемы. – EJP

ответ

2

Как отметил @markspace в комментарии, у вас в коде много забавных вещей. Вы должны сделать шаг назад, вернуться к интерфейсу командной строки и переработать всю свою структуру классов. Удалите эти внутренние классы, используйте некоторые интерфейсы, такие как MessageListener или ConnectionListnener, которые ваш клиент или сервер использует для общения с другими классами (например, с вашим графическим интерфейсом) о вещах, таких как полученные сообщения или созданное/потерянное соединение.

Когда вы сделали свой клиент основной метод должен выглядеть очень просто:

public static void main(String [] args) { 
    Client client = new Client("127.0.0.1"); 
    client.addMessageListener(new MessageListener() { 
     public void messageRecieved(String message) { 
      System.out.println(message); 
     } 
    }); 

    client.connect(); 
    System.out.println("Connected to server."); 
    Scanner scanner = new Scanner(System.in); 

    String userInput = null; 
    boolean quit = false; 
    do { 
     userInput = scanner.readLine(); 
     if(userInput != null && userInput.equals("quit")) { 
      client.sendMessage(userInput); 
     } else { 
      quit = true; 
     } 
    } while(!quit); 
} 

Конечно, я только что сделал это вверх, но его просто пример, как только у вас есть классовая структура должным образом разбиты и вещи, где они должно быть очень легко подключить графический интерфейс.

Список может продолжаться, но в нижней строке вы должны внимательно изучить, какие классы должны знать, какую информацию и почему. Разделяйте классы и делайте поля private и не делитесь информацией, если они не должны быть разделены! Важно, что вы действительно думаете об уменьшении code coupling.


В любом случае достаточно хаотичный и на актуальной проблеме с вашим кодом: в ServerClientFrontEnd.main у вас есть этот snipplet:

new ServerClientFrontEnd().startClient(); 

/* Create and display the form */ 
java.awt.EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     new ServerClientFrontEnd().setVisible(true); 
    } 
}); 

Вы создаете 2 экземпляра ServerClientFrontEnd, тот, который запускает клиент другой, что показывает графический интерфейс пользователя. Тот, который показывает GUI, является тем, где вы меняете строки List, а другой список всегда пуст. Чтобы заставить его работать, замените snipplet следующим образом:

/* Create and display the form */ 
java.awt.EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     ServerClientFrontEnd fontEnd = new ServerClientFrontEnd(); 
     fontEnd.startClient(); 
     fontEnd.setVisible(true); 
    } 
}); 
+0

Забыл, чтобы закрыть эту тему. Спасибо за ответ. –

Смежные вопросы