跟著實例學習java多線程4的簡單介紹

本文目錄一覽:

java多線程如何創建多個多線程

Java 多線程的同步依靠的是對象鎖機制,這個問題需要我們不斷的學習相關的問題。下面我們就來詳細的學習下如何才能更好的進行具體內容的使用。synchronized關鍵字的背後就是利用了封鎖來實現對共享資源的互斥訪問。

下面以一個簡單的實例來進行對比分析。實例要完成的工作非常簡單,就是創建10個線程,每個線程都列印從0到99這100個數字,我們希望線程之間不會出現交叉亂序列印,而是順序地列印。

先來看第一段代碼,這裡我們在run()方法中加入了synchronized關鍵字,希望能對run方法進行互斥訪問,但結果並不如我們希望那樣,這是因為這裡synchronized鎖住的是this對象,即當前運行線程對象本身。 Java 多線程代碼中創建了10個線程,而每個線程都持有this對象的對象鎖,這不能實現線程的同步。

Java多線程代碼如下

1.package com.vista;

2.class MyThread implements java.lang.Runnable

3.{

4.private int threadId;

5.public MyThread(int id)

6.{

7.this.threadId = id;

8.}

9.@Override

10.public synchronized void run()

11.{

12.for (int i = 0; i 100; ++i)

13.{

14.System.out.println(“Thread ID: ” + this.threadId + ” : ” + i);

15.}

16.}

17.}

18.public class ThreadDemo

19.{

20./**

21.* @param args

22.* @throws InterruptedException

23.*/

24.public static void main(String[] args) throws InterruptedException

25.{

26.for (int i = 0; i 10; ++i)

27.{

28.new Thread(new MyThread(i)).start();

29.Thread.sleep(1);

30.}

31.}

32.}

以上就是對Java多線程的詳細代碼介紹。

java多線程有幾種實現方法

繼承Thread類來實現多線程:

當我們自定義的類繼承Thread類後,該類就為一個線程類,該類為一個獨立的執行單元,線程代碼必須編寫在run()方法中,run方法是由Thread類定義,我們自己寫的線程類必須重寫run方法。

run方法中定義的代碼為線程代碼,但run方法不能直接調用,如果直接調用並沒有開啟新的線程而是將run方法交給調用的線程執行

要開啟新的線程需要調用Thread類的start()方法,該方法自動開啟一個新的線程並自動執行run方法中的內容

         

請點擊輸入圖片描述

結果:            

         

請點擊輸入圖片描述

*java多線程的啟動順序不一定是線程執行的順序,各個線程之間是搶佔CPU資源執行的,所有有可能出現與啟動順序不一致的情況。

CPU的調用策略:

如何使用CPU資源是由操作系統來決定的,但操作系統只能決定CPU的使用策略不能控制實際獲得CPU執行權的程序。

線程執行有兩種方式:

1.搶佔式:

目前PC機中使用最多的一種方式,線程搶佔CPU的執行權,當一個線程搶到CPU的資源後並不是一直執行到此線程執行結束,而是執行一個時間片後讓出CPU資源,此時同其他線程再次搶佔CPU資源獲得執行權。

2.輪循式;

每個線程執行固定的時間片後讓出CPU資源,以此循環執行每個線程執行相同的時間片後讓出CPU資源交給下一個線程執行。

如何學習java中的多線程

我可以結合自己的經驗大致給你說一說,希望對你有所幫助,少走些彎路。 學習Java其實應該上升到如何學習程序設計這種境界,其實學習程序設計又是接受一種編程思想。每一種語言的程序設計思想 大同小異,只是一些由語言特性的而帶來的細微差別,比如Java中的Interface,你幾乎在以前的學習中沒有碰到過。以下我 仔細給你說幾點: 1。我們必須明確一個大方向,也就是說現在面向對象的編程範疇。儘管人工智慧曾經有所浪潮(看看Borland為什麼有Turbo Prolog),但未來5-10年工業界廣泛承認並接受的將是面向對象式的編程。 2。工業界目前最流行的面向對象編程語言就是C++和Java。所以基本上鎖定這兩個方向就可以了。而且完全可以同時掌握。 3。掌握Java的精華特性而且一定要知道為什麼。比如,Interface和multi-thread。用interface是更好的多繼承的模型, 而多線程則是設計到語言一級的重要特性。要完全理解interface是為什麼,用多線程又有幾種常用的編程模型。 4。理解了語言的特性是為什麼了之後,就可以試著上升到設計這個層次,畢竟學習語言是要用的。目前比較好的開發模式是採用 自定向下的面向對象的設計,加上MVC的模式(你可以看一下我介紹的關於MVC的內容)。首先要找出最頂層的對象(這往往是最 難的),然後一層一層往下遞歸,記住每次應符合7+/-2的原則,因為我們人的短記憶就是這樣。一般有圖形用戶界面的應從界面 開始設計。 5。有了基本設計模型後,可以學一些設計模式(Design Pattern)。這是目前證明很有效的。比如體系結構模式(Layering分層, Pipe/Filter管道或過濾器),設計模式(有很多,比如對象池Object Pool、緩衝池Cache等),編程模式(比如Copy-on-Write)。 懂了這些模式之後,就會對系統的整體結構有很好的把握,而學術上也有傾向一個系統完全可以由各種模式組合而成。前面提到的MT實 際上就有好幾種模式,掌握後就不用自己花很多時間去試了。另外一個很重要的領域就是並行和分散式計算領域,大概有20種左右。 6。接下來就不能紙上談兵了,最好的方法其實是實踐。一般教科書上的例子並不能算是實踐,只能算是讓你掌握語言特性用的。而提倡 做實際的Project也不是太好,因為你還沒有熟練的能力去綜合各種技術,這樣只能是你自己越來越迷糊。我認為比較好的方法是找一些 比較經典的例子,每個例子比較集中一種編程思想而設計的,比如在我的實踐當中,我曾經學習過一個很經典的例子就是用Java實現的 HotDraw(源自SmallTalk),你可以用rolemodel或hotdraw在搜索引擎上找一下,我記不大清楚了。好象rolemodel.com是個網站, 上面有原代碼和一些基本設計的文檔。另一個來源可以到 是個不錯的文檔基地。從HotDraw上我學到了什麼是 Framework,以及如何用rolemodel的方式來構造,這樣我就可以應用到其他的地方。順便說一句,這個例子你絕對不會覺得小,只會覺 得大,並且他還是真正的商用的Framework。 7。結合前面學到的設計模式你就可以很好的理解這些經典的例子。並且自己可以用他來實現一些簡單的系統。如果可以對他進行進一步 的修改,找出你覺得可以提高性能的地方,加上自己的設計,那就更上一個層次了,也就會真正地感到有所收穫。 8。好象以上談的跟Java沒什麼關係,其實我們早就應該從單純的學習語言到真正的學習好編程的領域。學習技術是沒有止境的,你學習 第一種語言可能要半年時間,以後每種語言都不應該超過兩個月,否則你會覺得學習語言是包袱,是痛苦。 9。學習是為了用的,是為了讓你的程序產生價值,把握住這個原則會比較輕鬆點。 沒有第10點了,因為沒有東西是十全十美的,哈哈~~。 Happy Programming!

(一)Java多線程 (二)輸入輸出流 (三)Java網路編程 (四)Java資料庫編程

(1)多線程我感覺你應該知道首先實現線程類的兩個方法。一個是繼承Thread類.另一個是實現Runnable介面.然後怎樣啟動一個線程類。還有就是實現的兩種方法的區別。例如資源是不是能共享呀等等。

(2)對於輸入輸出流.你首先要明白任何輸出流輸入流都是繼承自OutputStream InputStream 還有Writer Reader。說得簡單一點所有字元流的祖先都是(Writer或者Reader)而所有位元組流的祖先都是

(OutputStream 或者InputStream)其中你還要明白字元和位元組的區別。最後以上所有的祖先都是抽象的。所以要實現都是通過多態來實現的。用父類的引用指用子類的實例。

(3)Java網路編程這個就不好說了。全得平時的理解加上網路課的學習

(4)java資料庫編程這個比較重要。首先你得知道。常用的資料庫有那些。然後怎樣讓java程序與資料庫連接起來。一般採用都是thin(對於oracle)然後。你得記住那些很固定的格式。例如什麼驅動的字元呀。還有就是url呀。等等各個資料庫是不一樣的。例如oralce你要載入驅動你得用Class.forName(“oracle.jdbc.driver.OracleDriver”);其中裡面的那個格式每個資料庫都不一樣。最後你得知道怎樣從資料庫裡面查詢一個你想要的結果。然後怎樣能過程序得到這個結果。這就是jdbc里提供的一些方法了。例如像什麼ResulSet對象呀。等等。總之多多練習就能了解的。

學習java多線程,這必須搞懂的這幾個概念,很重要

多線程:指的是這個程序(一個進程)運行時產生了不止一個線程

並行與並發:

並行:多個cpu實例或者多台機器同時執行一段處理邏輯,是真正的同時。

並發:通過cpu調度演算法,讓用戶看上去同時執行,實際上從cpu操作層面不是真正的同時。並發往往在場景中有公用的資源,那麼針對這個公用的資源往往產生瓶頸,我們會用TPS或者QPS來反應這個系統的處理能力。

如何用Java編寫多線程

在java中要想實現多線程,有兩種手段,一種是繼續Thread類,另外一種是實現Runable介面。

對於直接繼承Thread的類來說,代碼大致框架是:

?

123456789101112 class 類名 extends Thread{ 方法1; 方法2; … public void run(){ // other code… } 屬性1; 屬性2; … }

先看一個簡單的例子:

?

12345678910111213141516171819202122232425262728 /** * @author Rollen-Holt 繼承Thread類,直接調用run方法 * */class hello extends Thread { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i 5; i++) { System.out.println(name + “運行 ” + i); } } public static void main(String[] args) { hello h1=new hello(“A”); hello h2=new hello(“B”); h1.run(); h2.run(); } private String name; }

【運行結果】:

A運行 0

A運行 1

A運行 2

A運行 3

A運行 4

B運行 0

B運行 1

B運行 2

B運行 3

B運行 4

我們會發現這些都是順序執行的,說明我們的調用方法不對,應該調用的是start()方法。

當我們把上面的主函數修改為如下所示的時候:

?

123456 public static void main(String[] args) { hello h1=new hello(“A”); hello h2=new hello(“B”); h1.start(); h2.start(); }

然後運行程序,輸出的可能的結果如下:

A運行 0

B運行 0

B運行 1

B運行 2

B運行 3

B運行 4

A運行 1

A運行 2

A運行 3

A運行 4

因為需要用到CPU的資源,所以每次的運行結果基本是都不一樣的,呵呵。

注意:雖然我們在這裡調用的是start()方法,但是實際上調用的還是run()方法的主體。

那麼:為什麼我們不能直接調用run()方法呢?

我的理解是:線程的運行需要本地操作系統的支持。

如果你查看start的源代碼的時候,會發現:

?

1234567891011121314151617 public synchronized void start() { /** * This method is not invoked for the main method thread or “system” * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state “NEW”. */ if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } private native void start0();

注意我用紅色加粗的那一條語句,說明此處調用的是start0()。並且這個這個方法用了native關鍵字,次關鍵字表示調用本地操作系統的函數。因為多線程的實現需要本地操作系統的支持。

但是start方法重複調用的話,會出現java.lang.IllegalThreadStateException異常。

通過實現Runnable介面:

大致框架是:

?

123456789101112 class 類名 implements Runnable{ 方法1; 方法2; … public void run(){ // other code… } 屬性1; 屬性2; … }

來先看一個小例子吧:

?

123456789101112131415161718192021222324252627282930 /** * @author Rollen-Holt 實現Runnable介面 * */class hello implements Runnable { public hello() { } public hello(String name) { this.name = name; } public void run() { for (int i = 0; i 5; i++) { System.out.println(name + “運行 ” + i); } } public static void main(String[] args) { hello h1=new hello(“線程A”); Thread demo= new Thread(h1); hello h2=new hello(“線程B”); Thread demo1=new Thread(h2); demo.start(); demo1.start(); } private String name; }

【可能的運行結果】:

線程A運行 0

線程B運行 0

線程B運行 1

線程B運行 2

線程B運行 3

線程B運行 4

線程A運行 1

線程A運行 2

線程A運行 3

線程A運行 4

關於選擇繼承Thread還是實現Runnable介面?

其實Thread也是實現Runnable介面的:

?

12345678 class Thread implements Runnable { //… public void run() { if (target != null) { target.run(); } } }

其實Thread中的run方法調用的是Runnable介面的run方法。不知道大家發現沒有,Thread和Runnable都實現了run方法,這種操作模式其實就是代理模式。關於代理模式,我曾經寫過一個小例子呵呵,大家有興趣的話可以看一下:

Thread和Runnable的區別:

如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable介面的話,則很容易的實現資源共享。

?

1234567891011121314151617181920212223 /** * @author Rollen-Holt 繼承Thread類,不能資源共享 * */class hello extends Thread { public void run() { for (int i = 0; i 7; i++) { if (count 0) { System.out.println(“count= ” + count–); } } } public static void main(String[] args) { hello h1 = new hello(); hello h2 = new hello(); hello h3 = new hello(); h1.start(); h2.start(); h3.start(); } private int count = 5; }

【運行結果】:

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

大家可以想像,如果這個是一個買票系統的話,如果count表示的是車票的數量的話,說明並沒有實現資源的共享。

我們換為Runnable介面:

?

12345678910111213141516171819 /** * @author Rollen-Holt 繼承Thread類,不能資源共享 * */class hello implements Runnable { public void run() { for (int i = 0; i 7; i++) { if (count 0) { System.out.println(“count= ” + count–); } } } public static void main(String[] args) { hello he=new hello(); new Thread(he).start(); } private int count = 5; }

【運行結果】:

count= 5

count= 4

count= 3

count= 2

count= 1

總結一下吧:

實現Runnable介面比繼承Thread類所具有的優勢:

1):適合多個相同的程序代碼的線程去處理同一個資源

2):可以避免java中的單繼承的限制

3):增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立。

所以,本人建議大家勁量實現介面。

?

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/154432.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-16 14:12
下一篇 2024-11-16 14:12

相關推薦

  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Python生成隨機數的應用和實例

    本文將向您介紹如何使用Python生成50個60到100之間的隨機數,並將列舉使用隨機數的幾個實際應用場景。 一、生成隨機數的代碼示例 import random # 生成50個6…

    編程 2025-04-29
  • Python簡單數學計算

    本文將從多個方面介紹Python的簡單數學計算,包括基礎運算符、函數、庫以及實際應用場景。 一、基礎運算符 Python提供了基礎的算術運算符,包括加(+)、減(-)、乘(*)、除…

    編程 2025-04-29
  • Java判斷字元串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字元串中是否存在多個指定字元: 一、字元串遍歷 字元串是Java編程中非常重要的一種數據類型。要判斷字元串中是否存在多個指定字元…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29

發表回復

登錄後才能評論