Java多线程编程技术

1.       java和他的API都可以使用并发。可以指定程序包含不同的执行线程,每个线程都具有自己的方法调用堆栈和程序计数器,使得线程在与其他线程并发地执行能够共享程序范围内的资源,比如共享内存,这种能力被称为多线程编程(multithreading),在核心的C和C++语言中并不具备这种能力,尽管他们影响了JAVA的设计。

2.       线程的生命周期

新线程的生命周期从“新生”状态开始。程序启动线程前,线程一直是“新生”状态;程序启动线程后,线程进入“可运行”状态。“可运行”状态的线程,被认为是正在执行他的任务。

在程序启动线程之前,线程一直处于“等待”状态,只有当另一个线程通知正在等待的线程继续执行时,这个线程才会从“等待”状态恢复到“可运行”状态。

“可运行”状态的线程可以进入“定时等待”状态,等待一个指定的时间段。当时间到达或线程正在等待的某个事件发生时,该线程就会返回“可运行”状态。即使处理器可以使用,处于“定时等待”状态和“等待”状态的线程也不能用它。当处于“可运行”状态的线程正在等待另一个线程执行任务时,如果它提供了可选的等待时间段,则这个线程会进入“定时等待”状态。当另一个线程通知了这个线程,或者当定时的时间段到达时(以先满足的为准),这个线程就会返回到“可运行”状态.。使线程进入“定时等待”状态的另一方法是是处于“可运行”状态的线程睡眠。睡眠线程会在“定时等待”状态维持一个指定的时间段(称为睡眠时间段),过了这段时间,它会返回到“可运行”状态。当线程没有工作要执行时,它会立即睡眠。;例

当线程试图执行某个任务,而任务又不能立即完成,线程就从“可运行”状态转到“阻塞”状态。;例。即使有处理器可供使用,“阻塞”状态的线程也不能使用它。

线程成功完成任务,或者(由于出错)终止了时,“可运行”线程就会进入“终止”状态(有时称“停滞”状态)。

在操作系统级别,JAVA的“可运行”状态通常包含两个独立的状态。当线程首先从“新生”状态转到“可运行”状态,线程处于“就绪”状态。当操作系统将线程给处理器时,线程就从“就绪”状态进入“运行”状态(即开始执行),这也被称为“调度线程”。大多数操作系统中,每个线程被赋予一小段处理器时间(时间片)来执行任务。当时间片到达时,线程就会返回到“就绪”状态,而操作系统将另一个线程给予处理器。

3.       线程优先级与线程调度

JAVA的线程优先级范围为MIN_PRIORITY(常量1)到MAX_PRIORITY(常量10),默认是NORM_PRIORITY(常量5)

4.       创建并执行线程

创建线程推介实现Runnable接口

(1)Runnable与Thread类 

 1 // Fig. 4.1: PrintTask.java  
 2 
 3 // PrintTask class sleeps for a random time from 0 to 5 seconds  
 4 
 5 import java.util.Random;  
 6 
 7 public class PrintTask implements Runnable   
 8 
 9 {  
10 private final int sleepTime; // random sleep time for thread  
11 
12 private final String taskName; // name of task  
13 
14 private final static Random generator = new Random();  
15 
16 public PrintTask( String name )  
17 
18    {  
19       taskName = name; // set task name  
20 
21 // pick random sleep time between 0 and 5 seconds  
22 
23       sleepTime = generator.nextInt( 5000 ); // milliseconds  
24 
25    } // end PrintTask constructor  
26 
27 // method run contains the code that a thread will execute  
28 
29 public void run()  
30 
31    {  
32 try // put thread to sleep for sleepTime amount of time   
33 
34       {  
35          System.out.printf( "%s going to sleep for %d milliseconds.\n",   
36 
37             taskName, sleepTime );  
38          Thread.sleep( sleepTime ); // put thread to sleep  
39 
40       } // end try          
41 
42 catch ( InterruptedException exception )  
43 
44       {  
45          System.out.printf( "%s %s\n", taskName,  
46 
47 "terminated prematurely due to interruption" );  
48 
49       } // end catch  
50 
51 // print task name  
52 
53       System.out.printf( "%s done sleeping\n", taskName );   
54 
55    } // end method run  
56 
57 } // end class PrintTask  
[java] view plaincopy
 1 // Fig. 4.2  ThreadCreator.java  
 2 
 3 // Creating and starting three threads to execute Runnables.  
 4 
 5 import java.lang.Thread;  
 6 
 7 public class ThreadCreator  
 8 
 9 {  
10 
11 public static void main( String[] args )  
12 
13    {  
14 
15       System.out.println( "Creating threads" );  
16 
17 // create each thread with a new targeted runnable  
18 
19       Thread thread1 = new Thread( new PrintTask( "task1" ) );  
20 
21       Thread thread2 = new Thread( new PrintTask( "task2" ) );  
22 
23       Thread thread3 = new Thread( new PrintTask( "task3" ) );  
24 
25       System.out.println( "Threads created, starting tasks." );  
26 
27 // start threads and place in runnable state  
28 
29       thread1.start(); // invokes task1抯 run method  
30 
31       thread2.start(); // invokes task2抯 run method  
32 
33       thread3.start(); // invokes task3抯 run method  
34 
35       System.out.println( "Tasks started, main ends.\n" );  
36 
37    } // end main  
38 
39 } // end class RunnableTester   

 

(2)线程管理与Executor框架

       .5为显示的创建线程,但推介使用Executor接口,用来管理Runnable对象的执行。Executor对象创建并管理一组Runnable对象的线程,这组线程就做线程池(thread pool).优点是Executor对象能复用了已经有的线程,减少为每个任务创建新线程的开销,提高性能。

       Executor接口只声明了一个名称为execute的方法,接收一个Runnable实参。Executor会将传递给他的execute方法的每个Runnable对象赋予线程池中可以用的线程。如果没有可以用的线程,则Executor会创建一个新线程,或等待某个线程会成为可用的,并会将这个线程赋予传递给execute方法的Runnable对象。

       ExecutorService接口扩展了Executor接口。

[java] view plaincopy
 1 // Fig. 4.3: TaskExecutor.java  
 2 
 3 // Using an ExecutorService to execute Runnables.  
 4 
 5 import java.util.concurrent.Executors;  
 6 
 7 import java.util.concurrent.ExecutorService;  
 8 
 9 public class TaskExecutor  
10 
11 {  
12 
13 public static void main( String[] args )  
14 
15    {  
16 
17 // create and name each runnable  
18 
19       PrintTask task1 = new PrintTask( "task1" );  
20 
21       PrintTask task2 = new PrintTask( "task2" );  
22 
23       PrintTask task3 = new PrintTask( "task3" );  
24 
25       System.out.println( "Starting Executor" );  
26 
27 // create ExecutorService to manage threads  
28 
29       ExecutorService threadExecutor = Executors.newCachedThreadPool();  
30 
31 // start threads and place in runnable state  
32 
33       threadExecutor.execute( task1 ); // start task1     
34 
35       threadExecutor.execute( task2 ); // start task2  
36 
37       threadExecutor.execute( task3 ); // start task3  
38 
39 // shut down worker threads when their tasks complete  
40 
41       threadExecutor.shutdown();   
42 
43       System.out.println( "Tasks started, main ends.\n" );  
44 
45    } // end main  
46 
47 } // end class TaskExecutor 
  1. 5.       线程同步  

(1)线程同步(thread synchronization),协调多个并发线程对共享数据的访问。这种方式同步多个线程,就可以保证访问共享对象的每个线程都能同步地将其他所有线程排除在外,这被称为“互斥”。

另一个方法,使用JAVA内置的监控器(monitor)。每个对象都有一个监控器和监控锁(或内置锁)。监控器保证任何时候监控锁由具有最大可能的唯一一个线程持有。

(2)同步的数据共享:执行原子操作。

[java] view plaincopy
 1 // Adds integers to an array shared with other Runnables  
 2 
 3 import java.lang.Runnable;  
 4 
 5 public class ArrayWriter implements Runnable  
 6 
 7 {  
 8 private final SimpleArray sharedSimpleArray;  
 9 
10 private final int startValue;  
11 
12 public ArrayWriter( int value, SimpleArray array )  
13 
14    {  
15       startValue = value;  
16       sharedSimpleArray= array;  
17    } // end constructor  
18 
19 public void run()  
20 
21    {  
22 for ( int i = startValue; i < startValue + 3; i++ )  
23 
24       {  
25          sharedSimpleArray.add( i ); // add an element to the shared array  
26 
27       } // end for  
28 
29    } // end method run  
30 
31 } // end class ArrayWrite  

[java] view plaincopy

 1 // Fig 5.2: SharedArrayTest.java  
 2 
 3 // Executes two Runnables to add elements to a shared SimpleArray.  
 4 
 5 import java.util.concurrent.Executors;  
 6 
 7 import java.util.concurrent.ExecutorService;  
 8 
 9 import java.util.concurrent.TimeUnit;  
10 
11 public class SharedArrayTest  
12 
13 {  
14 public static void main( String[] arg )  
15 
16    {  
17 // construct the shared object  
18 
19       SimpleArray sharedSimpleArray = new SimpleArray( 6 );  
20 
21 // create two tasks to write to the shared SimpleArray  
22 
23       ArrayWriter writer1 = new ArrayWriter( 1, sharedSimpleArray );  
24 
25       ArrayWriter writer2 = new ArrayWriter( 11, sharedSimpleArray );  
26 
27 // execute the tasks with an ExecutorService  
28 
29       ExecutorService executor = Executors.newCachedThreadPool();  
30       executor.execute( writer1 );  
31       executor.execute( writer2 );  
32       executor.shutdown();  
33 try  
34 
35       {  
36 // wait 1 minute for both writers to finish executing  
37 
38 boolean tasksEnded = executor.awaitTermination(   
39 
40 1, TimeUnit.MINUTES );  
41 
42 if ( tasksEnded )  
43 
44             System.out.println( sharedSimpleArray ); // print contents  
45 
46 else  
47 
48             System.out.println(   
49 "Timed out while waiting for tasks to finish." );  
50 
51       } // end try  
52 
53 catch ( InterruptedException ex )  
54 
55       {  
56          System.out.println(   
57 "Interrupted while wait for tasks to finish." );  
58 
59       } // end catch  
60 
61    } // end main  
62 
63 } // end class SharedArrayTest  

[java] view plaincopy

 1 // Fig.5.3 : SimpleArray.java  
 2 
 3 // Class that manages an integer array to be shared by multiple   
 4 
 5 // threads with synchronization.  
 6 
 7 import java.util.Random;  
 8 
 9 public class SimpleArray  
10 
11 {  
12 private final int array[]; // the shared integer array  
13 
14 private int writeIndex = 0; // index of next element to be written  
15 
16 private final static Random generator = new Random();  
17 
18 // construct a SimpleArray of a given size  
19 
20 public SimpleArray( int size )  
21 
22    {  
23       array = new int[ size ];  
24 
25    } // end constructor  
26 
27 // add a value to the shared array  
28 
29 public synchronized void add( int value )  
30 
31    {  
32 int position = writeIndex; // store the write index  
33 
34 try  
35 
36       {  
37 // put thread to sleep for 0-499 milliseconds  
38 
39          Thread.sleep( generator.nextInt( 500 ) );   
40 
41       } // end try  
42 
43 catch ( InterruptedException ex )  
44 
45       {  
46          ex.printStackTrace();  
47       } // end catch  
48 
49 // put value in the appropriate element  
50 
51       array[ position ] = value;  
52       System.out.printf( "%s wrote %2d to element %d.\n",   
53 
54          Thread.currentThread().getName(), value, position );  
55       ++writeIndex; // increment index of element to be written next  
56 
57       System.out.printf( "Next write index: %d\n", writeIndex );  
58 
59    } // end method add  
60 
61 // used for outputting the contents of the shared integer array  
62 
63 public String toString()  
64 
65    {  
66       String arrayString = "\nContents of SimpleArray:\n";  
67 
68 for ( int i = 0; i < array.length; i++ )  
69 
70          arrayString += array[ i ] + " ";  
71 
72 return arrayString;  
73 
74    } // end method toString  
75 
76 } // end class SimpleArray

 

 

posted @ 2015-08-31 09:49  JDoran  阅读(384)  评论(0编辑  收藏  举报