zoukankan      html  css  js  c++  java
  • 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.
    ",   
    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
    ", 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
    ", 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.
    " );  
    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.
    " );  
    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.
    ",   
    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
    ", 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 = "
    Contents of SimpleArray:
    ";  
    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

     

  • 相关阅读:
    多线程编程核心技术(五)死锁
    SELinux详细配置
    Linux实现RAID
    iSCSi的基本配置
    文本超出省略号之前后省略号实现
    对象冻结
    条件判断的优美写法
    使用VConsole
    重绘和重排(回流)
    移动端rem布局
  • 原文地址:https://www.cnblogs.com/jdoran/p/4772311.html
Copyright © 2011-2022 走看看