java多线程编程技术 +代码实例

来源:互联网 发布:扮猪吃老虎 网游 知乎 编辑:程序博客网 时间:2024/04/28 04:49

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类

[java] view plain copy
  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.    
  8.   
  9. public class PrintTask implements Runnable   
  10.   
  11. {  
  12.   
  13.    private final int sleepTime; // random sleep time for thread  
  14.   
  15.    private final String taskName; // name of task  
  16.   
  17.    private final static Random generator = new Random();  
  18.   
  19.       
  20.   
  21.    public PrintTask( String name )  
  22.   
  23.    {  
  24.   
  25.       taskName = name; // set task name  
  26.   
  27.           
  28.   
  29.       // pick random sleep time between 0 and 5 seconds  
  30.   
  31.       sleepTime = generator.nextInt( 5000 ); // milliseconds  
  32.   
  33.    } // end PrintTask constructor  
  34.   
  35.    
  36.   
  37.    // method run contains the code that a thread will execute  
  38.   
  39.    public void run()  
  40.   
  41.    {  
  42.   
  43.       try // put thread to sleep for sleepTime amount of time   
  44.   
  45.       {  
  46.   
  47.          System.out.printf( "%s going to sleep for %d milliseconds.\n",   
  48.   
  49.             taskName, sleepTime );  
  50.   
  51.          Thread.sleep( sleepTime ); // put thread to sleep  
  52.   
  53.       } // end try          
  54.   
  55.       catch ( InterruptedException exception )  
  56.   
  57.       {  
  58.   
  59.          System.out.printf( "%s %s\n", taskName,  
  60.   
  61.             "terminated prematurely due to interruption" );  
  62.   
  63.       } // end catch  
  64.   
  65.           
  66.   
  67.       // print task name  
  68.   
  69.       System.out.printf( "%s done sleeping\n", taskName );   
  70.   
  71.    } // end method run  
  72.   
  73. // end class PrintTask  


[java] view plain copy
  1. // Fig. 4.2  ThreadCreator.java  
  2.   
  3. // Creating and starting three threads to execute Runnables.  
  4.   
  5. import java.lang.Thread;  
  6.   
  7.    
  8.   
  9. public class ThreadCreator  
  10.   
  11. {  
  12.   
  13.    public static void main( String[] args )  
  14.   
  15.    {  
  16.   
  17.       System.out.println( "Creating threads" );  
  18.   
  19.    
  20.   
  21.       // create each thread with a new targeted runnable  
  22.   
  23.       Thread thread1 = new Thread( new PrintTask( "task1" ) );  
  24.   
  25.       Thread thread2 = new Thread( new PrintTask( "task2" ) );  
  26.   
  27.       Thread thread3 = new Thread( new PrintTask( "task3" ) );  
  28.   
  29.    
  30.   
  31.       System.out.println( "Threads created, starting tasks." );  
  32.   
  33.    
  34.   
  35.       // start threads and place in runnable state  
  36.   
  37.       thread1.start(); // invokes task1抯 run method  
  38.   
  39.       thread2.start(); // invokes task2抯 run method  
  40.   
  41.       thread3.start(); // invokes task3抯 run method  
  42.   
  43.    
  44.   
  45.       System.out.println( "Tasks started, main ends.\n" );  
  46.   
  47.    } // end main  
  48.   
  49. // end class RunnableTester     
  50.   
  51.        

 

(2)线程管理与Executor框架

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

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

       ExecutorService接口扩展了Executor接口。

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


 

[java] view plain copy
  1.    
[java] view plain copy
  1. 5.       线程同步  

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

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

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

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


 

[java] view plain copy
  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.    
  12.   
  13. public class SharedArrayTest  
  14.   
  15. {  
  16.   
  17.    public static void main( String[] arg )  
  18.   
  19.    {  
  20.   
  21.       // construct the shared object  
  22.   
  23.       SimpleArray sharedSimpleArray = new SimpleArray( 6 );  
  24.   
  25.    
  26.   
  27.       // create two tasks to write to the shared SimpleArray  
  28.   
  29.       ArrayWriter writer1 = new ArrayWriter( 1, sharedSimpleArray );  
  30.   
  31.       ArrayWriter writer2 = new ArrayWriter( 11, sharedSimpleArray );  
  32.   
  33.    
  34.   
  35.       // execute the tasks with an ExecutorService  
  36.   
  37.       ExecutorService executor = Executors.newCachedThreadPool();  
  38.   
  39.       executor.execute( writer1 );  
  40.   
  41.       executor.execute( writer2 );  
  42.   
  43.    
  44.   
  45.       executor.shutdown();  
  46.   
  47.    
  48.   
  49.       try  
  50.   
  51.       {  
  52.   
  53.          // wait 1 minute for both writers to finish executing  
  54.   
  55.          boolean tasksEnded = executor.awaitTermination(   
  56.   
  57.             1, TimeUnit.MINUTES );  
  58.   
  59.    
  60.   
  61.          if ( tasksEnded )  
  62.   
  63.             System.out.println( sharedSimpleArray ); // print contents  
  64.   
  65.          else  
  66.   
  67.             System.out.println(   
  68.   
  69.                "Timed out while waiting for tasks to finish." );  
  70.   
  71.       } // end try  
  72.   
  73.       catch ( InterruptedException ex )  
  74.   
  75.       {  
  76.   
  77.          System.out.println(   
  78.   
  79.             "Interrupted while wait for tasks to finish." );  
  80.   
  81.       } // end catch  
  82.   
  83.    } // end main  
  84.   
  85. // end class SharedArrayTest  


 

[java] view plain copy
  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.    
  10.   
  11. public class SimpleArray  
  12.   
  13. {  
  14.   
  15.    private final int array[]; // the shared integer array  
  16.   
  17.    private int writeIndex = 0// index of next element to be written  
  18.   
  19.    private final static Random generator = new Random();  
  20.   
  21.    
  22.   
  23.    // construct a SimpleArray of a given size  
  24.   
  25.    public SimpleArray( int size )  
  26.   
  27.    {  
  28.   
  29.       array = new int[ size ];  
  30.   
  31.    } // end constructor  
  32.   
  33.    
  34.   
  35.    // add a value to the shared array  
  36.   
  37.    public synchronized void add( int value )  
  38.   
  39.    {  
  40.   
  41.       int position = writeIndex; // store the write index  
  42.   
  43.    
  44.   
  45.       try  
  46.   
  47.       {  
  48.   
  49.          // put thread to sleep for 0-499 milliseconds  
  50.   
  51.          Thread.sleep( generator.nextInt( 500 ) );   
  52.   
  53.       } // end try  
  54.   
  55.       catch ( InterruptedException ex )  
  56.   
  57.       {  
  58.   
  59.          ex.printStackTrace();  
  60.   
  61.       } // end catch  
  62.   
  63.    
  64.   
  65.       // put value in the appropriate element  
  66.   
  67.       array[ position ] = value;  
  68.   
  69.       System.out.printf( "%s wrote %2d to element %d.\n",   
  70.   
  71.          Thread.currentThread().getName(), value, position );  
  72.   
  73.    
  74.   
  75.       ++writeIndex; // increment index of element to be written next  
  76.   
  77.       System.out.printf( "Next write index: %d\n", writeIndex );  
  78.   
  79.    } // end method add  
  80.   
  81.      
  82.   
  83.    // used for outputting the contents of the shared integer array  
  84.   
  85.    public String toString()  
  86.   
  87.    {  
  88.   
  89.       String arrayString = "\nContents of SimpleArray:\n";  
  90.   
  91.      
  92.   
  93.       for ( int i = 0; i < array.length; i++ )  
  94.   
  95.          arrayString += array[ i ] + " ";  
  96.   
  97.      
  98.   
  99.       return arrayString;  
  100.   
  101.    } // end method toString  
  102.   
  103. // end class SimpleArray  
  104.   
  105.    
0 0
原创粉丝点击