java多線程編程技術(shù)詳解和實(shí)例代碼
java多線程編程技術(shù)詳解和實(shí)例代碼
1. Java和他的API都可以使用并發(fā)。
可以指定程序包含不同的執(zhí)行線程,每個(gè)線程都具有自己的方法調(diào)用堆棧和程序計(jì)數(shù)器,使得線程在與其他線程并發(fā)地執(zhí)行能夠共享程序范圍內(nèi)的資源,比如共享內(nèi)存,這種能力被稱為多線程編程(multithreading),在核心的C和C++語言中并不具備這種能力,盡管他們影響了JAVA的設(shè)計(jì)。
2. 線程的生命周期
新線程的生命周期從“新生”狀態(tài)開始。程序啟動(dòng)線程前,線程一直是“新生”狀態(tài);程序啟動(dòng)線程后,線程進(jìn)入“可運(yùn)行”狀態(tài)。“可運(yùn)行”狀態(tài)的線程,被認(rèn)為是正在執(zhí)行他的任務(wù)。
在程序啟動(dòng)線程之前,線程一直處于“等待”狀態(tài),只有當(dāng)另一個(gè)線程通知正在等待的線程繼續(xù)執(zhí)行時(shí),這個(gè)線程才會(huì)從“等待”狀態(tài)恢復(fù)到“可運(yùn)行”狀態(tài)。
“可運(yùn)行”狀態(tài)的線程可以進(jìn)入“定時(shí)等待”狀態(tài),等待一個(gè)指定的時(shí)間段。當(dāng)時(shí)間到達(dá)或線程正在等待的某個(gè)事件發(fā)生時(shí),該線程就會(huì)返回“可運(yùn)行”狀態(tài)。即使處理器可以使用,處于“定時(shí)等待”狀態(tài)和“等待”狀態(tài)的線程也不能用它。當(dāng)處于“可運(yùn)行”狀態(tài)的線程正在等待另一個(gè)線程執(zhí)行任務(wù)時(shí),如果它提供了可選的等待時(shí)間段,則這個(gè)線程會(huì)進(jìn)入“定時(shí)等待”狀態(tài)。當(dāng)另一個(gè)線程通知了這個(gè)線程,或者當(dāng)定時(shí)的時(shí)間段到達(dá)時(shí)(以先滿足的為準(zhǔn)),這個(gè)線程就會(huì)返回到“可運(yùn)行”狀態(tài).。使線程進(jìn)入“定時(shí)等待”狀態(tài)的另一方法是是處于“可運(yùn)行”狀態(tài)的線程睡眠。睡眠線程會(huì)在“定時(shí)等待”狀態(tài)維持一個(gè)指定的時(shí)間段(稱為睡眠時(shí)間段),過了這段時(shí)間,它會(huì)返回到“可運(yùn)行”狀態(tài)。當(dāng)線程沒有工作要執(zhí)行時(shí),它會(huì)立即睡眠。;例
當(dāng)線程試圖執(zhí)行某個(gè)任務(wù),而任務(wù)又不能立即完成,線程就從“可運(yùn)行”狀態(tài)轉(zhuǎn)到“阻塞”狀態(tài)。;例。即使有處理器可供使用,“阻塞”狀態(tài)的線程也不能使用它。
線程成功完成任務(wù),或者(由于出錯(cuò))終止了時(shí),“可運(yùn)行”線程就會(huì)進(jìn)入“終止”狀態(tài)(有時(shí)稱“停滯”狀態(tài))。
在操作系統(tǒng)級(jí)別,JAVA的“可運(yùn)行”狀態(tài)通常包含兩個(gè)獨(dú)立的狀態(tài)。當(dāng)線程首先從“新生”狀態(tài)轉(zhuǎn)到“可運(yùn)行”狀態(tài),線程處于“就緒”狀態(tài)。當(dāng)操作系統(tǒng)將線程給處理器時(shí),線程就從“就緒”狀態(tài)進(jìn)入“運(yùn)行”狀態(tài)(即開始執(zhí)行),這也被稱為“調(diào)度線程”。大多數(shù)操作系統(tǒng)中,每個(gè)線程被賦予一小段處理器時(shí)間(時(shí)間片)來執(zhí)行任務(wù)。當(dāng)時(shí)間片到達(dá)時(shí),線程就會(huì)返回到“就緒”狀態(tài),而操作系統(tǒng)將另一個(gè)線程給予處理器。
3. 線程優(yōu)先級(jí)與線程調(diào)度
JAVA的線程優(yōu)先級(jí)范圍為MIN_PRIORITY(常量1)到MAX_PRIORITY(常量10),默認(rèn)是NORM_PRIORITY(常量5)
4. 創(chuàng)建并執(zhí)行線程
創(chuàng)建線程推介實(shí)現(xiàn)Runnable接口
(1)Runnable與Thread類
// Fig. 4.1: PrintTask.java
// PrintTask class sleeps for a random time from 0 to 5 seconds
import java.util.Random;
public class PrintTask implements Runnable
{
private final int sleepTime; // random sleep time for thread
private final String taskName; // name of task
private final static Random generator = new Random();
public PrintTask( String name )
{
taskName = name; // set task name
// pick random sleep time between 0 and 5 seconds
sleepTime = generator.nextInt( 5000 ); // milliseconds
} // end PrintTask constructor
// method run contains the code that a thread will execute
public void run()
{
try // put thread to sleep for sleepTime amount of time
{
System.out.printf( "%s going to sleep for %d milliseconds.\n",
taskName, sleepTime );
Thread.sleep( sleepTime ); // put thread to sleep
} // end try
catch ( InterruptedException exception )
{
System.out.printf( "%s %s\n", taskName,
"terminated prematurely due to interruption" );
} // end catch
// print task name
System.out.printf( "%s done sleeping\n", taskName );
} // end method run
} // end class PrintTask
// Fig. 4.2 ThreadCreator.java
// Creating and starting three threads to execute Runnables.
import java.lang.Thread;
public class ThreadCreator
{
public static void main( String[] args )
{
System.out.println( "Creating threads" );
// create each thread with a new targeted runnable
Thread thread1 = new Thread( new PrintTask( "task1" ) );
Thread thread2 = new Thread( new PrintTask( "task2" ) );
Thread thread3 = new Thread( new PrintTask( "task3" ) );
System.out.println( "Threads created, starting tasks." );
// start threads and place in runnable state
thread1.start(); // invokes task1抯 run method
thread2.start(); // invokes task2抯 run method
thread3.start(); // invokes task3抯 run method
System.out.println( "Tasks started, main ends.\n" );
} // end main
} // end class RunnableTester
(2)線程管理與Executor框架
5為顯示的創(chuàng)建線程,但推介使用Executor接口,用來管理Runnable對(duì)象的執(zhí)行。Executor對(duì)象創(chuàng)建并管理一組Runnable對(duì)象的線程,這組線程就做線程池(thread pool).優(yōu)點(diǎn)是Executor對(duì)象能復(fù)用了已經(jīng)有的線程,減少為每個(gè)任務(wù)創(chuàng)建新線程的開銷,提高性能。
Executor接口只聲明了一個(gè)名稱為execute的方法,接收一個(gè)Runnable實(shí)參。Executor會(huì)將傳遞給他的execute方法的每個(gè)Runnable對(duì)象賦予線程池中可以用的線程。如果沒有可以用的線程,則Executor會(huì)創(chuàng)建一個(gè)新線程,或等待某個(gè)線程會(huì)成為可用的,并會(huì)將這個(gè)線程賦予傳遞給execute方法的Runnable對(duì)象。
ExecutorService接口擴(kuò)展了Executor接口。
// Fig. 4.3: TaskExecutor.java
// Using an ExecutorService to execute Runnables.
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class TaskExecutor
{
public static void main( String[] args )
{
// create and name each runnable
PrintTask task1 = new PrintTask( "task1" );
PrintTask task2 = new PrintTask( "task2" );
PrintTask task3 = new PrintTask( "task3" );
System.out.println( "Starting Executor" );
// create ExecutorService to manage threads
ExecutorService threadExecutor = Executors.newCachedThreadPool();
// start threads and place in runnable state
threadExecutor.execute( task1 ); // start task1
threadExecutor.execute( task2 ); // start task2
threadExecutor.execute( task3 ); // start task3
// shut down worker threads when their tasks complete
threadExecutor.shutdown();
System.out.println( "Tasks started, main ends.\n" );
} // end main
} // end class TaskExecutor
5. 線程同步
(1)線程同步(thread synchronization),協(xié)調(diào)多個(gè)并發(fā)線程對(duì)共享數(shù)據(jù)的訪問。這種方式同步多個(gè)線程,就可以保證訪問共享對(duì)象的每個(gè)線程都能同步地將其他所有線程排除在外,這被稱為“互斥”。
另一個(gè)方法,使用JAVA內(nèi)置的監(jiān)控器(monitor)。每個(gè)對(duì)象都有一個(gè)監(jiān)控器和監(jiān)控鎖(或內(nèi)置鎖)。監(jiān)控器保證任何時(shí)候監(jiān)控鎖由具有最大可能的唯一一個(gè)線程持有。
(2)同步的數(shù)據(jù)共享:執(zhí)行原子操作。
// Adds integers to an array shared with other Runnables
import java.lang.Runnable;
public class ArrayWriter implements Runnable
{
private final SimpleArray sharedSimpleArray;
private final int startValue;
public ArrayWriter( int value, SimpleArray array )
{
startValue = value;
sharedSimpleArray= array;
} // end constructor
public void run()
{
for ( int i = startValue; i < startValue + 3; i++ )
{
sharedSimpleArray.add( i ); // add an element to the shared array
} // end for
} // end method run
} // end class ArrayWrite
// Fig 5.2: SharedArrayTest.java
// Executes two Runnables to add elements to a shared SimpleArray.
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class SharedArrayTest
{
public static void main( String[] arg )
{
// construct the shared object
SimpleArray sharedSimpleArray = new SimpleArray( 6 );
// create two tasks to write to the shared SimpleArray
ArrayWriter writer1 = new ArrayWriter( 1, sharedSimpleArray );
ArrayWriter writer2 = new ArrayWriter( 11, sharedSimpleArray );
// execute the tasks with an ExecutorService
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute( writer1 );
executor.execute( writer2 );
executor.shutdown();
try
{
// wait 1 minute for both writers to finish executing
boolean tasksEnded = executor.awaitTermination(
1, TimeUnit.MINUTES );
if ( tasksEnded )
System.out.println( sharedSimpleArray ); // print contents
else
System.out.println(
"Timed out while waiting for tasks to finish." );
} // end try
catch ( InterruptedException ex )
{
System.out.println(
"Interrupted while wait for tasks to finish." );
} // end catch
} // end main
} // end class SharedArrayTest
// Fig.5.3 : SimpleArray.java
// Class that manages an integer array to be shared by multiple
// threads with synchronization.
import java.util.Random;
public class SimpleArray
{
private final int array[]; // the shared integer array
private int writeIndex = 0; // index of next element to be written
private final static Random generator = new Random();
// construct a SimpleArray of a given size
public SimpleArray( int size )
{
array = new int[ size ];
} // end constructor
// add a value to the shared array
public synchronized void add( int value )
{
int position = writeIndex; // store the write index
try
{
// put thread to sleep for 0-499 milliseconds
Thread.sleep( generator.nextInt( 500 ) );
} // end try
catch ( InterruptedException ex )
{
ex.printStackTrace();
} // end catch
// put value in the appropriate element
array[ position ] = value;
System.out.printf( "%s wrote %2d to element %d.\n",
Thread.currentThread().getName(), value, position );
++writeIndex; // increment index of element to be written next
System.out.printf( "Next write index: %d\n", writeIndex );
} // end method add
// used for outputting the contents of the shared integer array
public String toString()
{
String arrayString = "\nContents of SimpleArray:\n";
for ( int i = 0; i < array.length; i++ )
arrayString += array[ i ] + " ";
return arrayString;
} // end method toString
} // end class SimpleArray
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Java Collections集合繼承結(jié)構(gòu)圖_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java Collections集合繼承結(jié)構(gòu)圖_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下2017-04-04
java 獲取日期的幾天前,幾個(gè)月前和幾年前的實(shí)例
下面小編就為大家?guī)硪黄猨ava 獲取日期的幾天前,幾個(gè)月前和幾年前的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
教你用java完美封裝微信模板消息的發(fā)送動(dòng)態(tài)
這篇文章主要介紹了教你用java完美封裝微信模板消息的發(fā)送動(dòng)態(tài),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下2021-04-04
java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解
這篇文章主要為大家介紹了java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
線程池滿Thread?pool?exhausted排查和解決方案
這篇文章主要介紹了線程池滿Thread?pool?exhausted排查和解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Java超詳細(xì)教你寫一個(gè)銀行存款系統(tǒng)案例
這篇文章主要介紹了怎么用Java來寫一個(gè)銀行的存款系統(tǒng),銀行存款主要有賬號(hào)和存款金額兩個(gè)屬性,感興趣的朋友跟隨文章往下看看吧2022-03-03

