JAVA5 java.util.concurrent Implementation thread pool __java

Source: Internet
Author: User

http://www.ibm.com/developerworks/cn/java/j-zhanghz/



Level: Primary

Zhanghuang (zhanghuangzhu@gmail.com), software engineer

January 18, 2006 Java5 adds a new class library concurrency set Java.util.concurrent, which provides rich APIs for concurrent programs that are easier and more flexible in Java 5. This article through a network server model, to practice JAVA5 multithreaded programming, the model used in the JAVA5 thread pool, blocking queues, can be reset locks, but also practice callable, future and other interfaces, and the use of Java 5, another new feature generics.

This article will implement a network server model, once the client is connected to the server, start a new thread for the connection service, the service content to send some character information to the client. A typical network server model is as follows:

1. Establish the listening port.

2. Found a new connection, accept the connection, start the thread, execute the service thread.

3. Service complete, close the thread.

This model works well in most cases, but it takes a lot of time to process the user's request and the service is short for each request, and the system will spend a great deal of it on the creation and destruction of the threads. The Java 5 thread pool overcomes these drawbacks. By performing multiple tasks on a reusable thread, the cost of creating and destroying frequent threads is avoided and the performance of the server is greatly improved. Therefore, the network server model for this article will be as follows:

1. Set up the listening port and create the thread pool.

2. New connections are found, using the thread pool to perform service tasks.

3. Service complete, release thread to thread pool.

The following details how to implement this server using the APIs provided by the Java 5 concurrent package.




Back to the top of the page

Initialization involves creating a thread pool and initializing the listening port. Creating a thread pool can be created by calling the static method Newchahedthreadpool or Newfixedthreadpool in the Java.util.concurrent.Executors class. You can also perform a task by creating a new Java.util.concurrent.ThreadPoolExecutor instance. Here we use the Newfixedthreadpool method to build the thread pool.

Executorservice pool = Executors.newfixedthreadpool (10);
Represents a new thread pool with 10 threads in the thread pool serving task queues.

Use the ServerSocket object to initialize the listening port.

private static final int PORT = 19527;
Serverlistensocket = new ServerSocket (PORT);
Serverlistensocket.setreuseaddress (true);
Serverlistensocket.setreuseaddress (TRUE);




Back to the top of the page

When a new connection is established, the service task is submitted to the thread pool execution when accept returns.

while (true) {
socket socket = serverlistensocket.accept ();
Pool.execute (new Servicethread (socket));

This uses thread pool objects to execute threads, reducing the overhead of each thread creation and destruction. The thread is freed to the thread pool when the task finishes executing.




Back to the top of the page

The service thread Servicethread maintains a count to record the number of times the service thread was invoked. When the service task is invoked once, the value of Count is incremented by 1, so Servicethread provides a increasecount and GetCount method to increment the count value by 1 and get the count value. Because it is possible for multiple threads to compete and access count at the same time, you need a lock mechanism, and before Java 5, we can only use synchronized to lock. In Java 5, a more granular, more fine-grained, reentrant lock Reentrantlock is introduced. We use Reentrantlock to ensure code thread safety. Here is the specific code:

private static Reentrantlock lock = new Reentrantlock ();
private static int count = 0;
private int GetCount () {
	int ret = 0;
	try{
		Lock.lock ();
		ret = count;
	} finally{
		Lock.unlock ();
	}
	return ret;
}	
private void Increasecount () {
	try{
		lock.lock ();
		++count;
	} finally{
		Lock.unlock ();
	}

The service thread starts printing a welcome message to the client,

Increasecount ();
int curcount = GetCount ();
hellostring = "Hello, id =" + curcount+ "/r/n";
DOS = new DataOutputStream (Connectedsocket.getoutputstream ());
Dos.write (Hellostring.getbytes ());

A callable task is then submitted using the Executorservice Submit method, which returns a reference to the future interface. This practice is very effective for time-consuming tasks, after the submit task can continue to execute the following code, and then in the appropriate place can use the future get method to obtain the results, if the method has been completed, you do not have to wait to get the results, if still executing, then wait until run complete.

Executorservice executor = Executors.newsinglethreadexecutor ();
Future <String> Future = executor.submit (New Timeconsumingtask ());
Dos.write ("Let's Do Soemthing". GetBytes ());
String result = Future.get ();
Dos.write (Result.getbytes ());
Where Timeconsumingtask implements the callable interface
class Timeconsumingtask implements callable <string>{public
	String Call () throws Exception {
		System.out.println
		("It's" a time-consuming task, you 
		' d better retrieve, your result in the furture ");
		Return "OK, here's the result:it takes me lots of time to produce this result";
	}

Here, another new feature generic of Java 5 is used, and a string is used as the type parameter when declaring Timeconsumingtask. The call function of the callable interface must be implemented, similar to the Run function in runnable, where code to execute is written in the call function, and the return value type is equivalent to the type value passed in in the class declaration. In this program, we submit a callable task, then the program will not block, but continue to execute dos.write ("Let's Do Soemthing". GetBytes ()); When the program executes to string result = Future.get () If the call function has finished executing, gets the return value and, if it is still executing, waits for its execution to complete.




Back to the top of the page

The complete implementation code for the server side is as follows:

Package com.andrew;
Import Java.io.DataOutputStream;
Import java.io.IOException;
Import java.io.Serializable;
Import Java.net.ServerSocket;
Import Java.net.Socket;
Import Java.util.concurrent.ArrayBlockingQueue;
Import Java.util.concurrent.BlockingQueue;
Import java.util.concurrent.Callable;
Import java.util.concurrent.ExecutionException;
Import Java.util.concurrent.ExecutorService;
Import java.util.concurrent.Executors;
Import Java.util.concurrent.Future;
Import Java.util.concurrent.RejectedExecutionHandler;
Import Java.util.concurrent.ThreadPoolExecutor;
Import Java.util.concurrent.TimeUnit;
Import Java.util.concurrent.locks.ReentrantLock;
	public class Server {private static int producetasksleeptime = 100;
	private static int consumetasksleeptime = 1200;
	private static int producetaskmaxnumber = 100;
	private static final int core_pool_size = 2;
	private static final int max_pool_size = 100;
	private static final int keepalive_time = 3; private static final int queue_capacity = (Core_pool_size + max_pool_size)/2;
	private static final Timeunit time_unit = timeunit.seconds;
	private static final String HOST = "127.0.0.1";
	private static final int PORT = 19527;
	Private blockingqueue<runnable> Workqueue = new arrayblockingqueue<runnable> (queue_capacity);
	
	Private Threadpoolexecutor serverthreadpool = null;
	Private Executorservice pool = null;
	Private Rejectedexecutionhandler Rejectedexecutionhandler = new Threadpoolexecutor.discardoldestpolicy ();
	Private ServerSocket serverlistensocket = null;
	private int times = 5;
		public void Start () {//, can also init thread pool in this way. /*serverthreadpool = new Threadpoolexecutor (core_pool_size, Max_pool_size, Keepalive_time, TIME_UNIT, WorkQueue, R
		Ejectedexecutionhandler); */pool = Executors.newfixedthreadpool (10);
			try {serverlistensocket = new ServerSocket (PORT);
			Serverlistensocket.setreuseaddress (TRUE);
			System.out.println ("I ' m listening"); while (times--&Gt
				0) {Socket socket = serverlistensocket.accept ();
	String welcomestring = "Hello";
				Serverthreadpool.execute (new Servicethread (socket, welcomestring));
			Pool.execute (new Servicethread (socket));
		The catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();
	} cleanup ();
			public void Cleanup () {if (null!= serverlistensocket) {try {serverlistensocket.close ();
			catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();
		}//serverthreadpool.shutdown ();
	Pool.shutdown ();
		public static void Main (String args[]) {Server server = new server ();
	Server.start ();
	} class Servicethread implements Runnable, Serializable {private static final long serialversionuid = 0;
	Private Socket connectedsocket = null;
	Private String hellostring = null;
	private static int count = 0;
	private static Reentrantlock lock = new Reentrantlock (); Servicethread (socket socket) {Connectedsocket = socket;
		public void Run () {increasecount ();
		int curcount = GetCount ();
		hellostring = "Hello, id =" + curcount + "/r/n";
		Executorservice executor = Executors.newsinglethreadexecutor ();
		future<string> Future = executor.submit (New Timeconsumingtask ());
		DataOutputStream dos = null;
			try {dos = new DataOutputStream (Connectedsocket.getoutputstream ());
			Dos.write (Hellostring.getbytes ());
				try {dos.write ("Let's Do soemthing other./r/n". GetBytes ());
				String result = Future.get ();
			Dos.write (Result.getbytes ());
			catch (Interruptedexception e) {e.printstacktrace ();
			catch (Executionexception e) {e.printstacktrace ();
		The catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();
				finally {if (null!= connectedsocket) {try {connectedsocket.close ();
				catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();
} if (null!= dos) {try {					Dos.close ();
				catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();
		} executor.shutdown ();
		} private int GetCount () {int ret = 0;
			try {lock.lock ();
		ret = count;
		finally {Lock.unlock ();
	return ret;
			private void Increasecount () {try {lock.lock ();
		++count;
		finally {Lock.unlock ();
				Class Timeconsumingtask implements callable<string> {public String call () throws Exception {System.out
		. println ("It ' s a time-consuming task, you ' d better retrieve your result in the furture");
	Return "OK, here's the result:it takes me lots of time to produce this result";
 }
}

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.