最近看了几个多线程设计模式,对照J2SE5.0里的多线程工具,两者很相似。从网上找了几篇J2SE5.0多线程工具例子, 供参考
		
		(转自赛迪网)
		Java自1995年面世以来得到了广泛得一个运用,但是对多线程编程的支持Java很长时间一直停留在初级阶段。在Java 5.0之前Java里的多线程编程主要是通过Thread类,Runnable接口,Object对象中的wait()、 notify()、 notifyAll()等方法和synchronized关键词来实现的。这些工具虽然能在大多数情况下解决对共享资源的管理和线程间的调度,但存在以下几个问题
		
				1.      
				过于原始,拿来就能用的功能有限,即使是要实现简单的多线程功能也需要编写大量的代码。这些工具就像汇编语言一样难以学习和使用,比这更糟糕的是稍有不慎它们还可能被错误地使用,而且这样的错误很难被发现。
				
						
						
				
		
		
				2.      
				如果使用不当,会使程序的运行效率大大降低。
				
						
						
				
		
		
				3.      
				为了提高开发效率,简化编程,开发人员在做项目的时候往往需要写一些共享的工具来实现一些普遍适用的功能。但因为没有规范,相同的工具会被重复地开发,造成资源浪费。
				
						
						
				
		
		
				4.      
				因为锁定的功能是通过
				Synchronized
				来实现的,这是一种块结构,只能对代码中的一段代码进行锁定,而且锁定是单一的。如以下代码所示:
				
						
						
				
		
		
				
						
								| 
												synchronized
												(
												lock
												)
												{
										 
												
														 
														   //
												执行对共享资源的操作
												
														
														
												
										 
												
														    ……
										 
												}
										 | 
				
		
		
				     
				一些复杂的功能就很难被实现。比如说如果程序需要取得
				lock A
				和
				lock B
				来进行操作
				1
				,然后需要取得
				lock C
				并且释放
				lock A
				来进行操作
				2
				,
				Java 5.0
				之前的多线程框架就显得无能为力了。
				
						
						
				
		
		
				   因为这些问题,程序员对旧的框架一直颇有微词。这种情况一直到
				Java 5.0
				才有较大的改观,一系列的多线程工具包被纳入了标准库文件。这些工具包括了一个新的多线程程序的执行框架,使编程人员可方便地协调和调度线程的运行,并且新加入了一些高性能的常用的工具,使程序更容易编写,运行效率更高。本文将分类并结合例子来介绍这些新加的多线程工具。
				
						
						
				
		
		
				
						
						
				
		
		
				   在我们开始介绍
				Java 5.0
				里的新
				Concurrent
				工具前让我们先来看一下一个用旧的多线程工具编写的程序,这个程序里有一个
				Server
				线程,它需要启动两个
				Component
				,
				Server
				线程需等到
				Component
				线程完毕后再继续。相同的功能在
				Synchronizer
				一章里用新加的工具
				CountDownLatch
				有相同的实现。两个程序,孰优孰劣,哪个程序更容易编写,哪个程序更容易理解,相信大家看过之后不难得出结论。
				
						
						
				
		
		
				
						
								| 
												public class ServerThread {
										 
												
														      Object concLock = new Object();
										 
												
														      int count = 2;
										 
												public void runTwoThreads() {
										 
												
														      //
												启动两个线程去初始化组件
												
														
														
												
										 
												
														            new Thread(new ComponentThread1(this)).start();
										 
												
														            new Thread(new ComponentThread1(this)).start();
										 
												
														            // Wait for other thread
										 
												while(count != 0) {
										 
												
														                  synchronized(concLock) {
										 
												
														                        try {
										 
												
														                              concLock.wait();
										 
												
														                              System.out.println("Wake up.");
										 
												
														                        } catch (InterruptedException ie) { //
												处理异常
												}
										 
												
														                  }
										 
												
														            }
										 
												
														            System.out.println("Server is up.");
										 
												
														      }
										 
												
														      public void callBack() {
										 
												synchronized(concLock) {
										 
												
														                  count--;
										 
												
														                  concLock.notifyAll();
										 
												
														            }
										 
												
														      }
										 
												
														      public static void main(String[] args){
										 
												
														            ServerThread server = new ServerThread();
										 
												
														            server.runTwoThreads();
										 
												
														      }
										 
												}
										 
												 
										 
												public class ComponentThread1 implements Runnable {
										 
												
														      private ServerThread server;
										 
												
														      public ComponentThread1(ServerThread server) {
										 
												
														            this.server = server;
										 
												
														      }
										 
												public void run() {
										 
												
														      //
												做组件初始化的工作
												
														
														
												
										 
												
														            System.out.println("Do component initialization.");
										 
												
														            server.callBack();
										 
												
														      }
										 
												}
										 | 
				
		
		1:三个新加的多线程包
		
				   Java 5.0
				里新加入了三个多线程包:
				java.util.concurrent, java.util.concurrent.atomic, java.util.concurrent.locks. 
		
		
				- 
						java.util.concurrent
						包含了常用的多线程工具,是新的多线程工具的主体。
						
								
								
						
				
- 
						java.util.concurrent.atomic
						包含了不用加锁情况下就能改变值的原子变量,比如说
						AtomicInteger
						提供了
						addAndGet()
						方法。
						Add
						和
						Get
						是两个不同的操作,为了保证别的线程不干扰,以往的做法是先锁定共享的变量,然后在锁定的范围内进行两步操作。但用
						AtomicInteger.addAndGet()
						就不用担心锁定的事了,其内部实现保证了这两步操作是在原子量级发生的,不会被别的线程干扰。
						
								
								
						
				
- 
						java.util.concurrent.locks
						包包含锁定的工具。
						
								
								
						
				
2:Callable 和 Future接口
		
				   Callable
				是类似于
				Runnable
				的接口,实现
				Callable
				接口的类和实现
				Runnable
				的类都是可被其它线程执行的任务。
				Callable
				和
				Runnable
				有几点不同:
				
						
						
				
		
		
				- 
						Callable
						规定的方法是
						call()
						,而
						Runnable
						规定的方法是
						run().
				
- 
						Callable
						的任务执行后可返回值,而
						Runnable
						的任务是不能返回值的。
						
								
								
						
				
- 
						call
						()方法可抛出异常,而
						run
						()方法是不能抛出异常的。
						
								
								
						
				
- 
						运行
						Callable
						任务可拿到一个
						Future
						对象,通过
						Future
						对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
						
								
								
						
				
				以下是
				Callable
				的一个例子:
				
						
						
				
		
		
				
						
								| 
												public class DoCallStuff implements Callable{ // *1
										 
												
														        private int aInt;
										 
												
														        public DoCallStuff(int aInt) {
										 
												
														                this.aInt = aInt;
										 
												
														        }
										 
												
														        public String call() throws Exception { //*2
										 
												
														                boolean resultOk = false;
										 
												
														                if(aInt == 0){
										 
												
														                        resultOk = true;
										 
												
														                }  else if(aInt == 1){
										 
												
														                        while(true){ //infinite loop
										 
												
														                   
														             System.out.println("looping....");
										 
												
														                                Thread.sleep(3000);
										 
												
														                        }
										 
												
														                } else {
										 
												
														                        throw new Exception("Callable terminated with Exception!"); //*3
										 
												
														                }
										 
												
														                if(resultOk){
										 
												
														                        return "Task done.";
										 
												
														                } else {
										 
												
														                        return "Task failed";
										 
												
														                }
										 
												
														        }
										 
												}
										 | 
				
		
		
				*1: 
				名为
				DoCallStuff
				类实现了
				Callable
				,
				String
				将是
				call
				方法的返回值类型。例子中用了
				String
				,但可以是任何
				Java
				类。
				
						
						
				
		
		
				*2: call
				方法的返回值类型为
				String
				,这是和类的定义相对应的。并且可以抛出异常。
				
						
						
				
		
		
				*3: call
				方法可以抛出异常,如加重的斜体字所示。
				
						
						
				
		
		
				
						
						
				
		
		
				以下是调用
				DoCallStuff
				的主程序。
				
						
						
				
		
		
				import java.util.concurrent.ExecutionException;
		
		
				import java.util.concurrent.ExecutorService;
		
		
				import java.util.concurrent.Executors;
		
		
				import java.util.concurrent.Future;
		
		
				public class Executor {
		
		
				
						        public static void main(String[] args){
		
		
				
						                //*1
		
		
				
						                DoCallStuff call1 = new DoCallStuff(0);
		
		
				
						                DoCallStuff call2 = new DoCallStuff(1);
		
		
				
						                DoCallStuff call3 = new DoCallStuff(2);
		
		
				
						                //*2
		
		
				
						                ExecutorService es = Executors.newFixedThreadPool(3);
		
		
				
						                //*3
		
		
				
						                Future future1 = es.submit(call1);
		
		
				
						                Future future2 = es.submit(call2);
		
		
				
						     
						           Future future3 = es.submit(call3);
		
		
				
						                try {
		
		
				
						                        //*4
		
		
				
						                        System.out.println(future1.get());
		
		
				
						                         //*5
		
		
				
						                        Thread.sleep(3000);
		
		
				
						                  
						      System.out.println("Thread 2 terminated? :" + future2.cancel(true));
		
		
				
						                        //*6
		
		
				
						                        System.out.println(future3.get());
		
		
				
						                } catch (ExecutionException ex) {
		
		
				
						                        ex.printStackTrace();
		
		
				
						                } catch (InterruptedException ex) {
		
		
				
						                        ex.printStackTrace();
		
		
				
						                }
		
		
				
						        }
		
		
				}