Java Thread

Today, I started to add concurrent (multi-thread) capabilities to my Duke Web Server. In this post, I will refresh my knowledge in Java Thread mechanism.

Processes and Threads

In concurrent programming, there are two basic units of execution: processes and threads. In the world of Java, mostly time we are talking about Threads.

A process has a self-contained execution environment. Typically when we are talking process, we are talking a program or application. However, sometimes we also regards a set of cooperating processes as one program. For an example of process in Perl language, you can refer to my earlier post HTTP:Daemon in Perl

A thread sometimes is called lightweight process. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process.

How to define and start a Thread in Java

1. Implements Runnable interface. The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run.

Modifier and Type Method and Description
void run()

When an object implementing interface Runnable is used to create a thread, starting the thread causes the object’s run method to be called in that separately executing thread.

Here a sample class which supports Thread.

public class HelloRunnable implements Runnable {

    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }

}

2. Extend Thread class. The Thread class itself implements Runnable interface, though its run method does nothing – in other word, you have to overwrite its run in your class as above. As in Java, a class can implement many interfaces but extend only one class. Hence, developers usually choose the method 1 to implement their concurrent requirements.

public class HelloThread extends Thread {

    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new HelloThread()).start();
    }

}

Please note, you should invoke Thread.start in order to start the new thread. – Do NOT invoke the run method – it is just a common invoke like other methods – in other word, it does NOT support thread with run method!

For more details about Java Thread, you might refer to http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

Let’s see how I incorporate Java Thread into Duke Web Server.

For a synchronous implementation, you might refer to A Simple Servlet Container in Java

Basically, its steps should be,

1. Start a socket

2. Listening

3. Accept a request

4. Handle request

5. Start again from Step 3

Below are the steps support concurrent,

1. Start a socket

2. Listening

3. Accept a request – start a thread to handle the request – the thread will go to step 4

4. In the same time with Step 3, main process will come bck to Step 2 to wait for next request.

Below is the snippet,

package com.duke.moyan.connector;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class HttpAgent implements Runnable{

	private Socket socket = null;

	private void setSocket(Socket socket) {
		this.socket = socket;
	}

	public HttpAgent(Socket socket) {
		this.setSocket(socket);
	}

	@Override
	public void run() {
		try {
			BufferedReader input = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			OutputStream output = socket.getOutputStream();

			HttpRequest request = new HttpRequest(input);
			request.parse();

			HttpResponse response = new HttpResponse(output);
			response.setRequest(request);

			if (request.getUri().startsWith("/" + Constants.SERVLET_DIR +  "/")) {
				ServletProcessor processor = new ServletProcessor();
				processor.process(request, response);
			} else {
				StaticResourceProcessor processor = new StaticResourceProcessor();
				processor.process(request, response);
			}

			output.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("Close failed");
		}
	}

}

Start it,

		Socket socket = null;

		while (true) {
			try {
				socket = serverSocket.accept();
				System.out.println("Yes, accepted");
				//Thread.sleep(10000);
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("Accept failed: " + Constants.PORT);
				System.exit(-1);
			}

			Runnable httpthread;
			httpthread = new HttpAgent(socket);
			Thread thread = new Thread(httpthread);
			thread.start();
		}

You may fee interested in its package name ‘moyan’. Check it out http://en.wikipedia.org/wiki/Mo_Yan. I am just reading his novels. To salute to Mr. Moyan, I just named it with his name. 🙂