摘要:線程啟動后系統就自動調用方法。守護線程的使用必須在之前設置,否則會跑出一個異常。你不能把正在運行的常規線程設置為守護線程。在線程中產生的新線程也是的。線程的同步控制使用方法可以釋放對象鎖,使用或可以讓等待的一個或所有線程進入就緒狀態。
線程的創建 線程:程序中單個順序的流控制稱為線程
一個進程中可以含有多個線程
在操作系統中可以查看線程數
如:在Windows中,在任務管理器,右鍵,選擇列,選中“線程數”
一個進程中的多個線程分享CPU(并發的或以時間片的方式)
圖示如下:
共享內存(如多個線程訪問同一對象)
Java從語言級別支持多線程
如:
Object中wait(), notify(),java.lang中的類 Thread
線程啟動后,系統就自動調用run()方法。參考相關書:
所以我們自己調用run是不會產生新的線程的。
通常,run()方法執行一個時間較長的操作
如一個循環
顯示一系列圖片
下載一個文件
創建線程 1. 通過繼承Thread類創建線程可以實現新線程:class MyThread extends Thread { public void run() { for(int i=0;i<100;i++) { System.out.print (" " + i); public void run() { ...} } //生成新線程 Thread thread = new Thread(mytask); thread.start(); } }
然而,并不推薦上述方式。參閱了《Introduction to Java Programming》:
This approach is, however, not recommended because it mixes the task and the mechanism of running the task. Separating the task from the thread is a preferred design.
因為Thread中還有其他的方法,這樣可能會混淆了Thread中固有的機制。
Thread類的方法很多,如下:
所以,更好的方式是重新定義一個類來實現抽象類Runnable類,然后采用基于接口的對象注入的方式新建一個Thread的對象。如第二個方法。
2. 通過向Thread()構造方法傳遞Runnable對象來創建線程class MyTask implements Runnable { public void run() { ...} } //生成新線程 Thread thread = new Thread(mytask); thread.start(); }
圖示如下:
使用示例:
public class TestThread4Anonymous { public static void main(String args[]) { //匿名類 new Thread(){ public void run() { for(int i=0; i<10; i++) System.out.println(i); } }.start(); //Lambda表達式 new Thread( ( ) -> { for(int i=0; i<10; i++) System.out.println(" "+ i); } ).start(); } }線程的控制 對線程的基本控制
線程的啟動:thread.start()
線程的結束:常用的方法是設定一個標記變量,結束相應的循環及方法。
暫時阻止線程的執行,比如在線程中用暫停方法:thread.sleep( 1000 );
線程的優先級調用設定線程的優先級setPriority( int priority)方法,默認有以下三種
MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY
線程有兩種:
一類是普通線程(非Daemon線程)
在Java程序中,若還有非Demon線程,則整個程序就不會結束
一類是Daemon線程(守護線程,后臺線程)
使用setDaemon(true);如果普通線程結束了,則后臺線程自動終止。
注:垃圾回收線程是后臺線程
代碼public class daemon { public static void main(String args[]) { //創建子線程 Runnable t = new MyThread2(); Thread thread = new Thread(t); thread.setDaemon(true); thread.start(); System.out.println( "主線程開始運行." ); try{ Thread.sleep(500); } catch(InterruptedException ex){} System.out.println("主線程結束,子線程由于設置為守護線程,所以也應該提前結束."); } } class MyThread2 implements Runnable { public void run() { for(int i=0; i<10; i++ ){ System.out.println( "子線程應該循環10次,當前的第"+i+"次"); try{ Thread.sleep(100); } catch(InterruptedException ex){} } } }
輸出結果:
主線程開始運行. 子線程應該循環10次,當前的第0次 子線程應該循環10次,當前的第1次 子線程應該循環10次,當前的第2次 子線程應該循環10次,當前的第3次 子線程應該循環10次,當前的第4次 主線程結束,子線程由于設置為守護線程,所以也應該提前結束.
可以從上面看出,守護線程即使在運行中,也應該隨著主線程的結束而提前結束。
守護線程的使用:thread.setDaemon(true)必須在thread.start()之前設置,否則會跑出一個IllegalThreadStateException異常。你不能把正在運行的常規線程設置為守護線程。
在Daemon線程中產生的新線程也是Daemon的。
守護線程應該永遠不去訪問固有資源,如文件、數據庫,因為它會在任何時候甚至在一個操作的中間發生中斷。
線程的同步為什么線程需要同步:
同時運行的線程需要共享數據、就必須考慮其它線程的狀態與行為,這時就需要實現同步。
Java引入了對象互斥鎖的概念,來保證共享數據操作的完整性。
每個對象都對應于一個monitor(監視器),它上面 一個稱為“互斥鎖(lock, mutex)”的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。
關鍵字synchronized用來與對象的互斥鎖聯系。
synchronized的用法(2種)
對代碼片斷:
synchronized(對象){ 。。。。}
對某個方法:
synchronized放在方法聲明中,如
public synchronized void push(char c ){ 。。。。}
以上相當于對synchronized(this), 表示整個方法為同步方法。
線程的同步控制使用wait()方法可以釋放對象鎖,使用notify()或notifyAll()可以讓等待的一個或所有線程進入就緒狀態。
Java里面可以將wait()和notify()放在synchronized里面,是因為Java是這樣處理的:
在synchronized代碼被執行期間,線程調用對象的wait()方法,會釋放對象鎖標志,然后進入等待狀態,然后由其它線程調用notify()或者notifyAll()方法通知正在等待的線程。
并發的類JDK1.5中增加了更多的類,以便更靈活地使用鎖機制
Lock接口、ReentrantLock類,如下:
ReadWriteLock接口、ReentrantReadWriteLock類
如.writeLock(),.lock(), .readLock(),.unlock(),這些方法。
java.util.concurrent包中增加了一些方便的類
常用于很少寫入而讀取頻繁的對象
CopyOnWriteArrayList、 CopyOnWriteArraySet
ConcurrentHashMap
putIfAbsent(), remove(), replace()
ArrayBlockingQueue
使用線程池 線程池相關的類ExecutorService 接口、ThreadPoolExecutor 類
Executors 工具類
他們同樣位于Concurrent接口的實現下面,如下:
ExecutorService pool = Executors.newCachedThreadPool();
使用其execute( Runnable r)方法
代碼import java.util.concurrent.*; /** 創建線程池示例 */ public class ExecutorDemo { public static void main(String[] args) { // 創建線程池對象 ExecutorService executor = Executors.newCachedThreadPool(); // 提交任務到線程池 executor.execute(new PrintChar("a", 4)); executor.execute(new PrintChar("b", 2)); executor.execute(new PrintNum(2)); //關閉線程池 executor.shutdown(); } } class PrintChar implements Runnable { private char charToPrint; // The character to print private int times; // The times to repeat /** 給定打印次數,打印特定字符 */ public PrintChar(char c, int t) { charToPrint = c; times = t; }
輸出結果
aaaabb 1 2流式操作及并行流
這里是指Java8新增的函數式思想,并不是具體的文件輸入輸出流。使得某些編程語句更加流暢的表達。
比如,對數組進行流化:
Arrays.stream(a) .filter( i -> i>20 ) .map(i->i*i) .sorted() .distinct() .limit(10) .max();stream的操作種類
流操作分成兩類:
中間的 -中間的操作保持流打開狀態,并允許后續的操作。
如: filter sorted limit map
末端的 - 末端的操作必須是對流的最終操作。
如: max min count forEach findAny
流步驟從某個源頭獲得一個流。
執行一個或更多的中間的操作。
執行一個末端的操作。
如何得到流對于數組
Arrays.stream(ary)
對于collection (包括List)
用 list.stream()
對于Map,沒有流,但提供了類似的方法
如map.putIfAbsent
map.computeIfPresent
map.merge
代碼import java.util.*; class UseStream { public static void main(String[] args) { Lista = Arrays.asList(1,2,5,7,3); System.out.println( a.stream() .mapToInt(i->(int)i) .filter( i -> i>2 ) .map( i -> i*i ) .sorted() .distinct() .limit(10) .max() ); } }
運行結果:
OptionalInt[49]流的并行計算(略)
只需將上面代碼的.stream()換成 .parallelStream()。
其他都不變,就可以實現并行計算
可以說,stream就是為并行運算而生的,它封裝的并行計算的大量內部細節。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65946.html
摘要:實際工作并不是非此即彼,往往都是進程線程結合的方式。操作系統會保證當線程數不大于數目時,不同的線程運行于不同的上改善程序結構。關于操作系統內部如何創建銷毀進程線程,即為什么這些操作進程消耗會比線程大,還沒有搞明白。 一、淺層理解 進程是資源分配的最小單位,線程是CPU分配的最小單位——簡單明了的說明了進程與線程的區別特點,然而在實際工作中并沒有什么卵用。 二、多個維度下,進程與線程的優...
摘要:對多線程程序,單核與多核如何工作相關的探討我們程序員在編碼的時候,涉及到技術方案時,往往會忽略掉代碼對性能方面的影響,或者沒有足夠的敏感度來幫助自己判斷自己的技術方案對系統性能造成的影響。 對多線程程序,單核cpu與多核cpu如何工作相關的探討 我們程序員在編碼的時候,涉及到技術方案時,往往會忽略掉代碼對性能方面的影響,或者沒有足夠的敏感度來幫助自己判斷自己的技術方案對系統性能造成的影...
摘要:對多線程程序,單核與多核如何工作相關的探討我們程序員在編碼的時候,涉及到技術方案時,往往會忽略掉代碼對性能方面的影響,或者沒有足夠的敏感度來幫助自己判斷自己的技術方案對系統性能造成的影響。 對多線程程序,單核cpu與多核cpu如何工作相關的探討 我們程序員在編碼的時候,涉及到技術方案時,往往會忽略掉代碼對性能方面的影響,或者沒有足夠的敏感度來幫助自己判斷自己的技術方案對系統性能造成的影...
摘要:最近聽很多面試的小伙伴說,網上往往是一篇一篇的多線程的文章,除了書籍沒有什么學習多線程的一系列文章。將此線程標記為線程或用戶線程。 最近聽很多面試的小伙伴說,網上往往是一篇一篇的Java多線程的文章,除了書籍沒有什么學習多線程的一系列文章。但是僅僅憑借一兩篇文章很難對多線程有系統的學習,而且面試的時候多線程這方面的知識往往也是考察的重點,所以考慮之下決定寫一系列關于Java多線程的文章...
閱讀 3647·2021-09-27 14:02
閱讀 1787·2019-08-30 15:56
閱讀 1742·2019-08-29 18:44
閱讀 3273·2019-08-29 17:21
閱讀 485·2019-08-26 17:15
閱讀 1173·2019-08-26 13:57
閱讀 1238·2019-08-26 13:56
閱讀 2878·2019-08-26 11:30