title: Do multiple clients need multiple threads?
body: <pre><code>package General;
  
  import java.io.*;
  import java.net.*;
  import java.util.Scanner;
  
  
  class Server
  {
      public static final int PORT = 7777;    
      protected static final int HEIGHT = 525;    
      protected static final int WIDTH = 1680;    
      private double y1 = 300;    
      private double y2 = 300;    
      private Scanner scan;    
      private PrintStream printStream;    
      private ServerThread one;    
      private ServerThread two;    
  
      public static void main( String args[] ) throws IOException
      {
          System.out.println( "THIS IS THE RIGHT SERVER" );
          new Server().runServer();
      }
  
  
      public void runServer() throws IOException
      {
          ServerSocket serverSocket = new ServerSocket( PORT );
          System.out.println( "Server up &amp; ready for connection..." );
          while ( true )
          {
              Socket socket = serverSocket.accept();
              new ServerThread( socket ).start();
          }
      }
  
  
      public class ServerThread extends Thread
      {
          Socket socket;
  
          ServerThread( Socket socket )
          {
              this.socket = socket;
          }
  
  
          public void run()
          {
              try
              {
                  scan = new Scanner( socket.getInputStream() );
                  printStream = new PrintStream( socket.getOutputStream() );
                  System.out.println( "User " + scan.nextLine() + " has connected to the server." );
              }
              catch ( IOException e )
              {
                  e.printStackTrace();
              }
  
              for ( int j = 0; j &gt; -1; j++ )
              {
                  System.out.println( "nope" );
                  printStream.println( "not running" );
                  if ( scan.nextLine().equals( "started" ) )
                  {
                      printStream.println( "go" );
                      break;
                  }
                  System.out.println( "nope2" );
              }
  
              try
              {
                  System.out.println( "IM OUT" );
                  printStream.flush();
                  String message = null;
                  while ( ( message = scan.nextLine() ) != null )
                  {
                      if ( message.equals( "not started" ) || message.equals( "started" ) )
                      {
                          printStream.println( "lag" );
                      }
                      else
                      {
                          System.out.println( "Incoming client message: " + message );
                          String position = message.substring( 10 );
                          double positionDouble = Double.parseDouble( position );
                          String info = message.substring( 0, 8 );
                          if ( info.equals( "p1 y pos" ) )
                          {
                              y1 = positionDouble;
                              System.out.println( y1 );
                          }
                          else if ( info.equals( "p2 y pos" ) )
                          {
                              y2 = positionDouble;
                              System.out.println( y2 );
                          }
                          if ( info.equals( "p1 y pos" ) )
                          {
                              printStream.println( y2 );
                          }
                          else if ( info.equals( "p2 y pos" ) )
                          {
                              printStream.println( y1 );
                          }
                      }
                  }
                  socket.close();
              }
              catch ( IOException e )
              {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }
      }
  }
  
  package General;
  
  import java.awt.Color;
  import java.io.*;
  import java.net.*;
  import java.util.Scanner;
  
  import java.awt.Font;
  import java.awt.Graphics;
  import java.awt.Label;
  import java.awt.Rectangle;
  import java.awt.TextField;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.KeyEvent;
  import java.awt.event.KeyListener;
  
  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  import javax.swing.Timer;
  
  public class BallMover extends JPanel implements ActionListener, KeyListener
  {
  
      JFrame jf = new JFrame();    
      Timer tm = new Timer( 1, this );    
      protected TextField tf;    
      protected Label score1;    
      protected int p1s = 0;    
      protected Label score2;    
      protected int p2s = 0;    
      protected static final int HEIGHT = 525;    
      protected static final int WIDTH = 1680;    
      protected double y1 = 300;    
      protected double y2 = 300;    
      protected double velY1 = 1.5;    
      protected double velY2 = 1.5;    
      protected double ballx = WIDTH / 2;    
      protected double bally = HEIGHT / 2;    
      protected double velBall = 1.2;    
      protected int ballAngle;    
      protected Font hehe;    
      protected static final int OFFSET = 0;    
      Socket socket;    
      PrintStream fileStream;    
      Scanner scan1;    
  
      public BallMover() throws IOException
      {
          socket = new Socket( "localhost", PORT );
          scan1 = new Scanner( socket.getInputStream() );
          fileStream = new PrintStream( socket.getOutputStream() );
          fileStream.println( name );
  
          hehe = new Font( "Ariel", Font.PLAIN, 25 );
          Rectangle instructions = new Rectangle( WIDTH / 3 - 10, OFFSET );
          instructions.setLocation( 10, 0 );
          Rectangle score1Pos = new Rectangle( WIDTH / 3, OFFSET );
          score1Pos.setLocation( WIDTH / 3, 0 );
          Rectangle score2Pos = new Rectangle( WIDTH / 3, OFFSET );
          score2Pos.setLocation( 2 * WIDTH / 3, 0 );
          Rectangle screen = new Rectangle( WIDTH, HEIGHT );
          screen.setLocation( 0, 0 );
  
          tf = new TextField( "", 10 );
          tf.setBounds( new Rectangle( 5, 5 ) );
          tf.setFont( hehe );
          tf.setEditable( false );
          jf.add( tf );
          tf.addKeyListener( this );
  
          JLabel instruct = new JLabel( convertToMultiline(
              "Press: \n0 to restart \nq to change p1 padal direction \np to change p2 padal direction \ns to pause \ncy@ once you press 0"
                  + "&lt;/html&gt;" ) );
          instruct.setBounds( instructions );
          instruct.setFont( hehe );
          // jf.add( instruct );
  
          score1 = new Label( "Player 1 Score: " + p1s );
          score1.setBounds( score1Pos );
          score1.setFont( hehe );
          // jf.add( score1 );
  
          score2 = new Label( "Player 2 Score: " + p2s );
          score2.setBounds( score2Pos );
          score2.setFont( hehe );
          // jf.add( score2 );
  
          jf.setSize( WIDTH, HEIGHT );
          this.setBounds( screen );
          jf.add( this );
          jf.setTitle( "BallMover1" );
          jf.setVisible( true );
  
          if ( Math.random() &gt; .5 )
          {
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 315;
              }
              else
              {
                  ballAngle = (int)( Math.random() ) + 45;
              }
          }
          else
          {
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 135;
              }
              else
              {
                  ballAngle = (int)( Math.random() * 45 ) + 180;
              }
          }
          String command;
          while ( true )
          {
              command = scan1.nextLine();
              fileStream.println( "not started" );
              System.out.println( command );
              if ( command.equals( "go" ) )
              {
                  break;
              }
          }
          fileStream.flush();
      }
  
  
      public void paintComponent( Graphics g )
      {
          super.paintComponent( g );
          g.setColor( Color.RED );
          g.fillRect( 30, (int)y1, 30, 200 );
          g.fillRect( WIDTH - 80, (int)y2, 30, 200 );
          g.fillOval( (int)ballx, (int)bally, 40, 40 );
          g.drawLine( 0, OFFSET, WIDTH, OFFSET );
      }
  
  
      @Override
      public void keyTyped( KeyEvent e )
      {
          char input = e.getKeyChar();
          if ( input == 's' )
          {
              if ( tm.isRunning() )
              {
                  tm.stop();
              }
              else
              {
                  tm.start();
              }
          }
          if ( input == 't' )
          {
              System.out.println( "ballx: " + ballx );
              System.out.println( "bally: " + bally );
              System.out.println( "delta x: " + velBall * Math.cos( Math.toRadians( ballAngle ) ) );
              System.out.println( "delta y: " + velBall * Math.sin( Math.toRadians( ballAngle ) ) );
              System.out.println( "ball angle: " + ballAngle );
  
          }
          if ( input == '0' )
          {
              velBall = 1.05;
              ballx = WIDTH / 2;
              bally = HEIGHT / 2;
              fileStream.println( "started" );
              tm.start();
          }
          if ( input == 'q' )
          {
              velY1 *= -1;
          }
      }
  
  
      @Override
      public void keyPressed( KeyEvent e )
      {
      }
  
  
      @Override
      public void keyReleased( KeyEvent e )
      {
      }
  
  
      @Override
      public void actionPerformed( ActionEvent e )
      {
          System.out.println( "ballx: " + ballx );
          System.out.println( "bally: " + bally );
          System.out.println( "delta x: " + velBall * Math.cos( Math.toRadians( ballAngle ) ) );
          System.out.println( "delta y: " + velBall * Math.sin( Math.toRadians( ballAngle ) ) );
          System.out.println( "ball angle: " + ballAngle );
          System.out.println( "" );
          if ( y1 + 210 &gt; HEIGHT || y1 &lt;= OFFSET ) // p1 padal
          {
              if ( y1 &lt;= OFFSET )
              {
                  y1 = 5 + OFFSET;
              }
              velY1 *= -1;
          }
          if ( y2 + 210 &gt; HEIGHT || y2 &lt;= OFFSET )// p2 padal
          {
              if ( y2 &lt;= OFFSET )
              {
                  y2 = 5 + OFFSET;
              }
              velY2 *= -1;
          }
          y1 = y1 + velY1;
          y2 = y2 + velY2;
          if ( ballx &lt; 70 &amp;&amp; ballx &gt; 40 &amp;&amp; bally &gt;= y1 &amp;&amp; bally &lt;= y1 + 200 ) // bounce
                                                                              // off
                                                                              // p1
          {
              System.out.println( "bdoink1" );
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 315;
              }
              else
              {
                  ballAngle = (int)( Math.random() ) + 45;
              }
              velBall += .03;
          }
  
          if ( ballx &gt; WIDTH - 100 &amp;&amp; ballx &lt; WIDTH - 70 &amp;&amp; bally &gt;= y2 &amp;&amp; bally &lt;= y2 + 200 ) // bounce
                                                                                               // off
                                                                                               // p2
          {
              System.out.println( "bdoink2" );
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 135;
              }
              else
              {
                  ballAngle = (int)( Math.random() * 45 ) + 180;
              }
              velBall += .03;
          }
  
          if ( ballx &lt; 0 ) // Player 2 Wins
          {
              p2s++;
              score2.setText( "Player 2 Score: " + p2s );
              tm.stop();
          }
          if ( ballx &gt; WIDTH ) // Player 1 Wins
          {
              p1s++;
              score1.setText( "Player 1 Score: " + p1s );
              tm.stop();
          }
          if ( bally &gt; HEIGHT - 50 || bally &lt;= OFFSET ) // touches bottom or top
                                                        // wall
          {
              if ( bally &lt;= OFFSET )
              {
                  bally = 5 + OFFSET;
              }
              ballAngle *= -1;
          }
          ballx += velBall * Math.cos( Math.toRadians( ballAngle ) );
          bally += velBall * Math.sin( Math.toRadians( ballAngle ) );
  
          // send info to server
          System.out.println( "hi1" );
          fileStream.println( "p1 y pos: " + y1 );
          System.out.println( "hi2" );
          String work = scan1.nextLine();
          System.out.println( "hi3" );
          if ( work.equals( "lag" ) )
          {
              System.out.println( "hi4" );
          }
          else
          {
              y2 = Double.parseDouble( work );
          }
          System.out.println( "hi5" );
          repaint();
  
      }
  
  
      public static String convertToMultiline( String orig )
      {
          return "&lt;html&gt;" + orig.replaceAll( "\n", "&lt;br&gt;" );
      }
  
      // Client
      public static final int PORT = 7777;
  
      protected static final String name = "client1";
  
  
      public static void main( String args[] ) throws IOException
      {
          new BallMover();
      }
  }
  
  package General;
  
  import java.awt.Color;
  import java.io.*;
  import java.net.*;
  import java.util.Scanner;
  
  import java.awt.Font;
  import java.awt.Graphics;
  import java.awt.Label;
  import java.awt.Rectangle;
  import java.awt.TextField;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.KeyEvent;
  import java.awt.event.KeyListener;
  
  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  import javax.swing.Timer;
  
  
  public class BallMover2 extends JPanel implements ActionListener, KeyListener
  {
  
      JFrame jf = new JFrame();    
      Timer tm = new Timer( 1, this );    
      protected TextField tf;    
      protected Label score1;    
      protected int p1s = 0;    
      protected Label score2;    
      protected int p2s = 0;    
      protected static final int HEIGHT = 525;    
      protected static final int WIDTH = 1680;    
      protected double y1 = 300;    
      protected double y2 = 300;    
      protected double velY1 = 1.5;    
      protected double velY2 = 1.5;    
      protected double ballx = WIDTH / 2;    
      protected double bally = HEIGHT / 2;    
      protected double velBall = 1.2;    
      protected int ballAngle;    
      protected Font hehe;    
      protected static final int OFFSET = 0;    
      Socket socket;    
      PrintStream fileStream;    
      Scanner scan1;    
  
      public BallMover2() throws IOException
      {
          socket = new Socket( "localhost", PORT );
          scan1 = new Scanner( socket.getInputStream() );
          fileStream = new PrintStream( socket.getOutputStream() );
          fileStream.println( name );
  
          hehe = new Font( "Ariel", Font.PLAIN, 25 );
          Rectangle instructions = new Rectangle( WIDTH / 3 - 10, OFFSET );
          instructions.setLocation( 10, 0 );
          Rectangle score1Pos = new Rectangle( WIDTH / 3, OFFSET );
          score1Pos.setLocation( WIDTH / 3, 0 );
          Rectangle score2Pos = new Rectangle( WIDTH / 3, OFFSET );
          score2Pos.setLocation( 2 * WIDTH / 3, 0 );
          Rectangle screen = new Rectangle( WIDTH, HEIGHT );
          screen.setLocation( 0, 0 );
  
          tf = new TextField( "", 10 );
          tf.setBounds( new Rectangle( 5, 5 ) );
          tf.setFont( hehe );
          tf.setEditable( false );
          jf.add( tf );
          tf.addKeyListener( this );
  
          JLabel instruct = new JLabel( convertToMultiline(
              "Press: \n0 to restart \nq to change p1 padal direction \np to change p2 padal direction \ns to pause \ncy@ once you press 0"
                  + "&lt;/html&gt;" ) );
          instruct.setBounds( instructions );
          instruct.setFont( hehe );
          // jf.add( instruct );
  
          score1 = new Label( "Player 1 Score: " + p1s );
          score1.setBounds( score1Pos );
          score1.setFont( hehe );
          // jf.add( score1 );
  
          score2 = new Label( "Player 2 Score: " + p2s );
          score2.setBounds( score2Pos );
          score2.setFont( hehe );
          // jf.add( score2 );
  
          jf.setSize( WIDTH, HEIGHT );
          this.setBounds( screen );
          jf.add( this );
          jf.setTitle( "BallMover2" );
          jf.setVisible( true );
  
          if ( Math.random() &gt; .5 )
          {
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 315;
              }
              else
              {
                  ballAngle = (int)( Math.random() ) + 45;
              }
          }
          else
          {
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 135;
              }
              else
              {
                  ballAngle = (int)( Math.random() * 45 ) + 180;
              }
          }
          String command;
          while ( true )
          {
              command = scan1.nextLine();
              fileStream.println( "not started" );
              System.out.println( command );
              if ( command.equals( "go" ) )
              {
                  break;
              }
          }
          fileStream.flush();
      }
  
  
      public void paintComponent( Graphics g )
      {
          super.paintComponent( g );
          g.setColor( Color.RED );
          g.fillRect( 30, (int)y1, 30, 200 );
          g.fillRect( WIDTH - 80, (int)y2, 30, 200 );
          g.fillOval( (int)ballx, (int)bally, 40, 40 );
          g.drawLine( 0, OFFSET, WIDTH, OFFSET );
      }
  
  
      @Override
      public void keyTyped( KeyEvent e )
      {
          char input = e.getKeyChar();
          if ( input == 's' )
          {
              if ( tm.isRunning() )
              {
                  tm.stop();
              }
              else
              {
                  tm.start();
              }
          }
          if ( input == 't' )
          {
              System.out.println( "ballx: " + ballx );
              System.out.println( "bally: " + bally );
              System.out.println( "delta x: " + velBall * Math.cos( Math.toRadians( ballAngle ) ) );
              System.out.println( "delta y: " + velBall * Math.sin( Math.toRadians( ballAngle ) ) );
              System.out.println( "ball angle: " + ballAngle );
  
          }
          if ( input == '0' )
          {
              velBall = 1.05;
              ballx = WIDTH / 2;
              bally = HEIGHT / 2;
              fileStream.println( "started" );
              tm.start();
          }
          if ( input == 'p' )
          {
              velY2 *= -1;
          }
      }
  
  
      @Override
      public void keyPressed( KeyEvent e )
      {
      }
  
  
      @Override
      public void keyReleased( KeyEvent e )
      {
      }
  
  
      @Override
      public void actionPerformed( ActionEvent e )
      {
          System.out.println( "ballx: " + ballx );
          System.out.println( "bally: " + bally );
          System.out.println( "delta x: " + velBall * Math.cos( Math.toRadians( ballAngle ) ) );
          System.out.println( "delta y: " + velBall * Math.sin( Math.toRadians( ballAngle ) ) );
          System.out.println( "ball angle: " + ballAngle );
          System.out.println( "" );
          if ( y1 + 210 &gt; HEIGHT || y1 &lt;= OFFSET ) // p1 padal
          {
              if ( y1 &lt;= OFFSET )
              {
                  y1 = 5 + OFFSET;
              }
              velY1 *= -1;
          }
          if ( y2 + 210 &gt; HEIGHT || y2 &lt;= OFFSET )// p2 padal
          {
              if ( y2 &lt;= OFFSET )
              {
                  y2 = 5 + OFFSET;
              }
              velY2 *= -1;
          }
          y1 = y1 + velY1;
          y2 = y2 + velY2;
          if ( ballx &lt; 70 &amp;&amp; ballx &gt; 40 &amp;&amp; bally &gt;= y1 &amp;&amp; bally &lt;= y1 + 200 ) // bounce
                                                                              // off
                                                                              // p1
          {
              System.out.println( "bdoink1" );
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 315;
              }
              else
              {
                  ballAngle = (int)( Math.random() ) + 45;
              }
              velBall += .03;
          }
  
          if ( ballx &gt; WIDTH - 100 &amp;&amp; ballx &lt; WIDTH - 70 &amp;&amp; bally &gt;= y2 &amp;&amp; bally &lt;= y2 + 200 ) // bounce
                                                                                               // off
                                                                                               // p2
          {
              System.out.println( "bdoink2" );
              if ( Math.random() &gt; .5 )
              {
                  ballAngle = (int)( Math.random() * 45 ) + 135;
              }
              else
              {
                  ballAngle = (int)( Math.random() * 45 ) + 180;
              }
              velBall += .03;
          }
  
          if ( ballx &lt; 0 ) // Player 2 Wins
          {
              p2s++;
              score2.setText( "Player 2 Score: " + p2s );
              tm.stop();
          }
          if ( ballx &gt; WIDTH ) // Player 1 Wins
          {
              p1s++;
              score1.setText( "Player 1 Score: " + p1s );
              tm.stop();
          }
          if ( bally &gt; HEIGHT - 50 || bally &lt;= OFFSET ) // touches bottom or top
                                                        // wall
          {
              if ( bally &lt;= OFFSET )
              {
                  bally = 5 + OFFSET;
              }
              ballAngle *= -1;
          }
          ballx += velBall * Math.cos( Math.toRadians( ballAngle ) );
          bally += velBall * Math.sin( Math.toRadians( ballAngle ) );
  
          // send info to server
          System.out.println( "hi1" );
          fileStream.println( "p2 y pos: " + y2 );
          System.out.println( "hi2" );
          String work = scan1.nextLine();
          System.out.println( "hi3" );
          if ( work.equals( "lag" ) )
          {
              System.out.println( "hi4" );
          }
          else
          {
              y1 = Double.parseDouble( work );
          }
          System.out.println( "hi5" );
          repaint();
  
      }
  
  
      public static String convertToMultiline( String orig )
      {
          return "&lt;html&gt;" + orig.replaceAll( "\n", "&lt;br&gt;" );
      }
  
      // Client
      public static final int PORT = 7777;
  
      protected static final String name = "client2";
  
  
      public static void main( String args[] ) throws IOException
      {
          new BallMover2();
      }
  }
  </code></pre>
  
  <p>I am trying to make a pong game with 2 different clients. I made a server that would gather the information from the two pedals and frequently update the pedal locations. Whenever I run my code with 2 clients, the first client stops feeding information to the server. I was wondering if multiple clients need multiple threads. If so, how? Thanks.</p>