?
Solved

Threads...

Posted on 2003-03-06
14
Medium Priority
?
283 Views
Last Modified: 2010-03-31
Hi, I am developing a simple multi-threaded server.

I have one button to start listening on a given port(START), and another one to stop listening(STOP).

I can't seem to get them to work properly, and i have reverted to killing the thread on STOP and creating a new one every time START is pushed.

I know there is a way to use wait() and notify(), but when i try, the gui freezes up

Please let me how to get this to work better.
0
Comment
Question by:kmule81
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 3
  • +2
14 Comments
 

Expert Comment

by:CoenMeerbeek
ID: 8079024
Could you give a us some more information? Some code of your project? Thnx
0
 
LVL 35

Expert Comment

by:TimYates
ID: 8079062
class PortListener implements Runnable
{
  private volatile Thread runner = null ;
  private int port ;
  private ServerSocket ss ;

  public PortListener( int port )
  {
    this.port = port ;
  }

  public void start()
  {
    if( runner == null )
    {
      runner = new Thread( this ) ;
      ss = new ServerSocket( port ) ;
      runner.start() ;
    }
  }

  public void run()
  {
    while( runner != null )
    {
      // put your listen code here
    }
  }
 
  public void stop()
  {
    ss.close() ;
    runner = null ;
  }
}

...

PortListener pl = new PortListener() ;
pl.start() ;

...

pl.stop() ;

...

pl.start() ;
0
 
LVL 35

Expert Comment

by:TimYates
ID: 8079064
Or something similar...
0
Optimize your web performance

What's in the eBook?
- Full list of reasons for poor performance
- Ultimate measures to speed things up
- Primary web monitoring types
- KPIs you should be monitoring in order to increase your ROI

 

Author Comment

by:kmule81
ID: 8080963
This is very similar to what i have now.  The only difference is that you declared the 'runner' to be volatile.

So, I shouldn't be telling a thread to wait and then later telling it to resume (notify)?

For some reason, i thought that was preferred
0
 

Author Comment

by:kmule81
ID: 8081034
Also, with that code, my GUI will freeze up every once in a while (after repeatedly starting and stopping the thread), which i cant understand.

This is what i have...

       ...(in constructor)
       stopButton.addActionListener (new ActionListener()
            {
                public void actionPerformed(ActionEvent e){
              if(threadRunning) {
               stopButton.setEnabled(false);
               startButton.setEnabled(true);
                         stopServer();
              }
                }
            });

        startButton.addActionListener (new ActionListener()
            {
                public void actionPerformed(ActionEvent e){
              if(!threadRunning) {
               startButton.setEnabled(false);
               stopButton.setEnabled(true);
                         startServer();
              }
                }
            });
       .....


    public void startServer(){

        if(runner == null) {
         threadRunning = true;
            runner = new Thread(this);
            runner.start();
        } else {
         runner = null;
         startServer();
        }
    }

    public void stopServer(){
        if(runner != null) {
            threadRunning = false;
         try { ss.close();    } catch(Exception e)System.out.println(e);}
        }
    }
   public void run() {
        port=Integer.parseInt(portInput.getText());
        display("Server Started on Port: " + port + "\n");

        try {
            ss = new ServerSocket(port);
            while(true) {
                display("Listening again ** port: " + port + "\n");
                Socket s = ss.accept();
                new Thread(new FileRequest(s,this)).start();
                display("Got a file request... \n");
            }

        }  catch (Exception e) {System.out.println(e);}
    }

    public synchronized void display(String text) {
        a.append(text);
    }
0
 
LVL 2

Expert Comment

by:karlika
ID: 8082688
The version you have is the best you can get from java.
It is simply impossible to pause a java-socket.

The GUI usually freezes when you produce a deadlock or infinite loop in the event-thread. I personally bundle all event-handling in an inner class.

This makes debugging much more confortable.

Marko
0
 

Author Comment

by:kmule81
ID: 8085417
Marko,

Do you mean that instead of calling the stop and start functions, i should just do my actions right there?

Could you show me an example of what you mean?
0
 
LVL 2

Accepted Solution

by:
karlika earned 200 total points
ID: 8086831
The stopServer and startServer methods are actually called by the event-thread because they are results of clicking on the corresponding buttons. So if you produce a deadlock or tell this thread to wait() the event-thread is locked and will not take any actions (like clicking on the buttons) - the GUI freezes.

For easier debugging I put any Listeners in an inner class.

e.g.:

public class Server{

  private Button startButton;
  private Button stopButton;

  public class Listener implements ActionListener{
    public void actionPerformed(ActionEvent ae){
      if(ae.getSource()==startButton)startServer();
      if(ae.getSource()==stopButton)stopServer();
    }
    private void startServer(){
      ....
    }
    private void stopServer(){
      ....
    }
  }
 
  Listener listener = new Listener();

  public Server(){
    //initialize
    startButton = new Button("Start");
    startButton.addActionListener(listener);
    stopButton = new Button("Stop");
    stopButton.addActionListener(listener);
  }
}


But it doesn't make any difference in how your code is handeld. It's just a cosmetic operation to make it easier to find possible deadlocks in the event-thread.

Marko
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8087536
You need a ServerSocket object in the main method which will act as a listener to the port and whenever it accepts a new connection, it will start a new thread (meaning that it'll instantiate an object of a class which extends Thread or implements Runnable. The run () method of this class should contain all the functionality of the server (whatever it is supposed to do for every client) and wherever you wish to terminate the thread, just put a return statement. You don't even need to call wait () or notify () anywhere. It'll be automatically handled. You must have an infinte while loop in the run () method which will go as long as the client is connected and the moment the client disconnects, the client system will either send an appropriate packet (I don't know your protocol) or else the client might get disconnected due to a power failure, following which there'll be a SocketException which can be caught - that is where you should terminate th thread.

import java.net.* ;
import java.io.* ;

class ServerThread extends Thread
{
  Socket s ;
  InputStream is ;
  OutputStream os ;

  ServerThread ( Socket ss ) // constructor ()
  {
    s = ss ;
    is = s.getInputStream () ; // for reading from the client
    os = s.getOutputStream () ; // for sending to the client

    start () ;

  } // end of constructor ()

  public void run ()
  {
    try
    {
      while ( true )
      {
        // entire functionality of the server

        // suppose you wish to kill the thread here
           return ;

      } // end while

    } // end of try block

    catch ( SocketException se ) // client disconnected due to power-failure or something
    {
      return ; // kill this thread

    } // end of catch block

  } // end of run ()

} // class definition over

class MainApp
{
  public static void main ( String args[] )
  {
    ServerSocket ss = new ServerSocket ( 2025 ) ; // assuming 2025 to be the port number
   
    while ( true ) // or whatever condition - like the clicking of the Stop button - the code will be a little different
    {
      Socket s = ss.accept () ;
      new ServerThread ( s ) ;
     
    } // end while
   
  } // end of main ()
   
} // class definition over

If you need more help, please ask.

Mayank.
0
 
LVL 2

Expert Comment

by:karlika
ID: 8087665
This is what we had before, but the thread will run into eternity, because ss.accept() blocks until a connection is made, or an Exception is raised.

Marko
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8087700
Nopes! It doesn't - the threads (along with the main  thread)will be executing parallelly.

Mayank.
0
 
LVL 2

Expert Comment

by:karlika
ID: 8087853
Sorry, you are right. It's not exactly the same. You are using the main-thread to get the connections (it is blocked until the connect or an Exception).
After a connect you start a new Thread to handle the servertasks.

Kmule's code starts a GUI; the event-thread (by clicking the startButton) starts a receiverThread, with the ServerSocket listening. If a connection is received, the line:
" new Thread(new FileRequest(s,this)).start();"
starts a new thread to run the servertask.

I'm pretty sure, all of those threads will run parallelly.

Marko
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8110264
Kmule81,

You don't seem to be content with the answers. If so, please specify what more do you want so that we can help you out.

Mayank.
0
 

Author Comment

by:kmule81
ID: 8152744
Thank you both for all your help.

I am sorry for the delay, I was away for the week.

mayankeagle- thanks for another way of looking at the problem, but i went with the original one.

Kenny
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
Suggested Courses
Course of the Month10 days, 9 hours left to enroll

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question