日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java高级-多线程编程

發布時間:2024/9/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java高级-多线程编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

一、進程和線程? ??????

????????在java語言中最大的特點就是支持多線程的開發(也是為數不多支持多線程開發的語言),如果對多線程沒有一個全面而且細致的了解,在以后一定存在嚴重的技術缺陷。

????? ? 進程:傳統的dos是單進程處理,允許一個程序執行,后來到了Windows時代,出現了多線程的設計。表示在一個時間段上可以運行多個程序,并且這些程序將進行資源的輪流搶占。在同一時間點上,只有一個程序執行,后來有了多核CPU的實現。可以實現在同一時間點,多個程序同時執行。

????? ? 線程:是進程的基礎之上劃分的更小的程序單元,線程依賴于進程的實現,線程的啟動要比進程快的多。

二、Thread實現多線程

?范例:? 多線程主體類

class MyThread extends Thread{private String title;public MyThread(String title){this.title = title;}@Overridepublic void run() {for (int i = 0; i< 10; i++) {System.out.println(this.title+"運行,i="+i);}} }

? ? 多線程要執行的功能都應該在run()方法中進行定義,run()方法不能被直接調用(如果我們直接調用子線程的run()方法,其方法還是運行在主線程中,代碼在程序中是順序執行的,所以不會有解決耗時操作的問題。所以不能直接調用線程的run()方法,只有子線程開始了,才會有異步的效果。當thread.start()方法執行了以后,子線程才會執行run()方法,這樣的效果和在主線程中直接調用run()方法的效果是截然不同的)。所以如果要開啟多線程,必須執行start()方法。

public static void main(String[] args) {new MyThread("線程A").start();new MyThread("線程B").start();new MyThread("線程C").start(); }

? ?執行結果:線程A,B,C交替執行,執行順序不可控。

???結論:雖然調用是start()方法,但是最終執行的是run()方法。

? ?疑問:為什么不直接使用run()方法,而使用start()?

? ?start()源碼:

public synchronized void start() {if (threadStatus != 0)throw new IllegalThreadStateException();group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {}} } private native void start0();

? ? 分析start()方法源代碼:拋出“IllegalThreadStateException”異常,沒有throws也沒有try..catch,表明此異常一定是RuntimeException的子類。一個線程只允許啟動一次,否則就會拋出此異常。

? ? 列如:

public static void main(String[] args) {Thread t = new MyThread("線程A");t.start();t.start(); }

? ? native含義:

? ? 在java執行過程中考慮到對于不同層次的開發者的需求,所以java支持有本地的操作系統函數調用,而這項技術成為JNI技術,但是Java開發過程中并不推薦這樣使用,這項技術可以使用一些底層函數進行一些特殊的處理,而在start()方法里面的start0()表示需要將此方法依賴于不同的操作系統實現。

三、Runnable接口實現多線程

范例:Runnable實現

class MyThread implements Runnable{private String title;public MyThread(String title){this.title = title;}@Overridepublic void run() {for (int i = 0; i< 10; i++) {System.out.println(this.title+"運行,i="+i);}} }

? ? 此方式避免了單繼承的局限,也能更好的進行功能擴展。以后的開發中,優先考慮Runnable來實現,但是啟動多線程永遠都是通過Thread對象來啟動多線程。

????lambda表達式寫法:

public static void main(String[] args) {for (int i =0; i <3 ; i++){String title="線程對象_"+i;Runnable run=()->{for (int j = 0; j< 10; j++){System.out.println(title+"運行,j="+j);}};new Thread(run).start();}}

更簡潔:

public static void main(String[] args) {for (int i =0; i <3 ; i++){String title="線程對象_"+i;new Thread(()->{for (int j = 0; j< 10; j++){System.out.println(title+"運行,j="+j);}}).start();}}

四、Thread和Runnable的關系

? ? Thread也是Runnable接口的子類

? ? 關系圖:

????多線程的設計過程中,使用了代理模式,用戶自定義的MyThread的類只負責項目核心功能的實現嗎,而所有的輔助實現全部由Thread類來處理。

? ? 調用start()方法時候,通過Thread的構造函數傳遞了一個Runnable的接口對象,此對象將會被target保存,最終調用的將是Runnable子類覆蓋了Runnable接口的run()方法。

多線程開發示意圖:

范例:通過賣票程序來實現多個線程的資源并發訪問

class MyThread implements Runnable{private int ticket = 5;@Overridepublic void run() {for (int i = 0; i< 100; i++) {if(this.ticket> 0) {System.out.println("賣票,ticket=" + ticket--);}}} }public class Main {public static void main(String[] args) {MyThread mt = new MyThread();new Thread(mt).start();new Thread(mt).start();new Thread(mt).start();} }

執行結果:

內存分析:

五、Callable實現多線程

????如果要實現多線程,肯定依靠的是Runnable,但是Runnable中的run()沒有返回值。所以JDK1.5后出現java.util.concurrent.Callable來實現多線程。

? ? 接口的定義:

@FunctionalInterface public interface Callable<V> {V call() throws Exception; }

從定義可以發現Callable定義了一個泛型,此泛型的類型就是返回數據的類型,這樣的好處是避免向下轉型的安全隱患。

Callable的相關關系圖:

實例:Callable的線程實現

import java.util.concurrent.Callable; import java.util.concurrent.FutureTask;class MyThread implements Callable<String>{@Overridepublic String call() throws Exception {for(int i = 0; i< 10 ; i++){System.out.println("線程執行,i="+i);}return "程序執行完畢";} }public class Main {public static void main(String[] args) {try {FutureTask<String> task = new FutureTask<>(new MyThread());new Thread(task).start();System.out.println("【線程返回數據】"+task.get());}catch(Exception e){e.printStackTrace();}} }

執行結果:

注:Runnable和Callable的區別?

1.Runnable是在JDK1.0的時候提出的多線程的實現接口,而Callable是在JDK1.5以后提出的。

2.java.util.Runnable接口只有一個run()方法,沒有返回值,java.util.concurrent.Callable接口里面只有一個call()方法,可以有返回值。

六、線程的運行狀態

對于多線程的開發而言,總是先定義線程主題類,通過Thread進行線程的啟動,當你調用start()方法并不意味著線程已經啟動。

線程的運行狀態:

1.任何一個線程對象都應該使用Thread來進行封,并且通過start()進行啟動,啟動的時候,線程就會進入一種就緒狀態,并沒有執行。

2.進入到就緒狀態后,就需要等待資源調度,當某一個線程調度成功后進入運行狀態(run()),但是所有的線程不可能一直持續的執行下去,中間需要產生一些暫停的狀態。例如:某個線程執行一段時間后讓出資源,而后,這個線程就將進入阻塞狀態。隨后重新回到就緒狀態。

3.當run()方法執行完畢后,線程的主要任務也就完成了,此時就可以進入停止狀態。

轉載于:https://my.oschina.net/chenzhou/blog/2049677

總結

以上是生活随笔為你收集整理的java高级-多线程编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。