views:

120

answers:

5

All,

What is a really simple way of having a program do more than one thing at once, even if the computer does not necessarily have multiple 'cores'. Can I do this by creating more than one Thread?

My goal is to be able to have two computers networked (through Sockets) to respond to each-other's requests, while my program will at the same time be able to be managing a UI. I want the server to potentially handle more than one client at the same time as well.

My understanding is that the communication is done with BufferedReader.readLine() and PrintWriter.println(). My problem is that I want the server to be waiting on multiple readLine() requests, and also be doing other things. How do I handle this?

Many thanks,

Jonathan

+1  A: 

Have a look at this page: http://www.ashishmyles.com/tutorials/tcpchat/index.html -- it gives a good description of threads, UI details, etc, and gives a chat example where they merge the two together.

Also, consider using Apache MINA. It's quite lightweight, doesn't rely on any external libraries (apart from slf4j) and makes it very easy to get stuff from sockets without needing to go around in as loop, and it's also quite non-blocking (or blocking when you need it to be). So, you have a class which implements IoHandler and then you register that with an acceptor or some other Mina connection class. Then, it notifies you about when packets are received. It handles all the usually-crippling backend stuff for you in a pleasant way (i.e., manually creating multiple threads for clients and then managing these).

It also has codec support, where you can transform sent and received messages. So, say you want to receive Java objects on either end of your connection -- this will do the conversion for you. Perhaps you also want to zip them up to make it more efficient? You can write that too, adding that to the chain below the object codec.

Chris Dennett
Thanks for the quick response. I will take a look.
Jonathan
That had some useful information, but only briefly mentioned my threading issue. Thanks, but it didn't answer my question.
Jonathan
+1  A: 

Yes, just create multiple threads. They will run concurrently, whether or not the processor has multiple cores. (With a single core, the OS simply suspends the execution of the running thread at certain points and runs another thread for a while, so in effect, multiple ones seem to be running at the same time).

Here's a good concurrency tutorial: http://java.sun.com/docs/books/tutorial/essential/concurrency/

RarrRarrRarr
+1  A: 

Yes, you can do this by having multiple threads inside your Java program.

As the mechanisms in Java gets rather complicated when you do this, have a look at the appropriate section in the Java Tutorial:

http://java.sun.com/docs/books/tutorial/essential/concurrency/

Thorbjørn Ravn Andersen
Thank you. I understand the general concept of concurrency. I worked with it in an abstract sense during a high school internship position at Intel. Now I finally know how to implement it in Java.
Jonathan
And remember to sleep threads at least for a quarter of a second, so it doesn't beat the multi threading behavior.
Ben
"sleep threads"? No no, you don't want to do that. If you need to synchronize, use a synchronizer. Otherwise, don't interfere with scheduling unless you have a good reason to.
Enno Shioji
+1  A: 

The standard Java tutorial for Sockets is a good start. I wrote the exact program you are describing using this as a base. The last point on the page "Supporting Multiple Clients" describes how threads are implemented.

http://java.sun.com/docs/books/tutorial/networking/sockets/clientServer.html

Collin Price
I actually have been working primarily out of this tutorial and, to a lesser extent, a number of others. I did not find the Multiple Client section you mentioned very conclusive for one with little understanding of such things. Thanks anyways.
Jonathan
+1  A: 

Can I do this by creating more than one Thread?

What is a really simple way of having a program do more than one thing at once, even if the computer does not necessarily have multiple 'cores'. Can I do this by creating more than one Thread?


If you have 1 single core, then "official" only 1 task can be executed at the same time. Because your computer s processor is so fast and executes so many instructions per second it creates the illusion that your computer is doing multiple tasks simultaneously while every small unit it only executes 1 task. You can create this illusion in Java by creating threads which get scheduled by your operating system to run for a short period of time.

My advice is to have a look at the java.util.concurrent package because it contains a lot of helpful tools to make playing around with threads a lot easier(Back in the days when this package did not exists it was a lot harder). I for example like to use

ExecutorService es = Executors.newCachedThreadPool();

to create a thread pool which I can submit tasks to run simultaneously. Then when I have task which I like to have run, I call

es.execute(runnable);

where runnable looks like:

Runnable runnable = new Runnable() {
  public void run() {
      // code to run.
   }
};

For example say you run the following code:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mytests;

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
 * @author alfred
 */
public class Main {

    /**
     * @param args the command line arguments
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        // TODO code application logic here
        final CountDownLatch latch = new CountDownLatch(2);
        final long start = System.nanoTime();
        ExecutorService es = Executors.newCachedThreadPool();
        Runnable runnable = new Runnable() {
            public void run() {
                sleep(1);
                System.out.println(new Date());
                latch.countDown();
            }
        };
        es.submit(runnable);
        es.submit(runnable);
        latch.await(); // waits only latch.countDown() has been called 2 times.
        // 1 nanoseconds is equal to 1/1000000000 of a second.
        long total = (System.nanoTime() - start) / 1000000;
        System.out.println("total time: " + total);
        es.shutdown();
    }

    public static void sleep(int i) {
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException ie) {}
    }
}

The output would look like

run:
Fri Apr 02 03:34:14 CEST 2010
Fri Apr 02 03:34:14 CEST 2010
total time: 1055
BUILD SUCCESSFUL (total time: 1 second)

But I ran 2 tasks which each both ran for at least 1 second(because of sleep of 1 second). If I would run those 2 tasks sequentially then it would take at least 2 seconds, but because I used threads it only took 1 second. This is what you wanted and it is easily accomplished using the java.util.concurrent package.

I want the server to potentially handle more than one client at the same time as well.

My goal is to be able to have two computers networked (through Sockets) to respond to each-other's requests, while my program will at the same time be able to be managing a UI. I want the server to potentially handle more than one client at the same time as well.


I would advice you to have a look at Netty framework(MINA which also developed by the creator of MINA, but Netty is better(more development) in my opinion).:

The Netty project is an effort to provide an asynchronous event-driven network application framework and tools for rapid development of maintainable high performance & high scalability protocol servers & clients.

It will do all the heavy lifting for you. When I read the user guide I was totally amazed with netty. Netty uses nio which is for highly concurrent servers the new way to do IO which scales much better. Like I said before this framework does all the heavy lifting for you

My problem is that I want the server to be waiting on multiple readLine() requests, and also be doing other things

My understanding is that the communication is done with BufferedReader.readLine() and PrintWriter.println(). My problem is that I want the server to be waiting on multiple readLine() requests, and also be doing other things. How do I handle this?

Again when you look into the netty's user guide + examples you will find out that it does all the heavy lifting for you in an efficient way. You will only have to specify some simple callbacks to get the data from the clients.


Hopefully this has answered all your question. Else I would advice you to leave a comment so that I will try to explain it better.

Alfred