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 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 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 plain copy 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 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 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 - 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
转载于:https://www.cnblogs.com/jdoran/p/4772311.html
