[高併發]Java高併發編程系列開山篇--線程實現

来源:http://www.cnblogs.com/hyhnet/archive/2017/01/04/6250264.html
-Advertisement-
Play Games

Java是最早開始有併發的語言之一,再過去傳統多任務的模式下,人們發現很難解決一些更為複雜的問題,這個時候我們就有了併發. 引用 & 160; & 160; & 160; & 160;多線程比多任務更加有挑戰。多線程是在同一個程式內部並行執行,因此會對相同的記憶體空間進行併發讀寫操作。這可能是在單線程 ...


Java是最早開始有併發的語言之一,再過去傳統多任務的模式下,人們發現很難解決一些更為複雜的問題,這個時候我們就有了併發.
引用

       多線程比多任務更加有挑戰。多線程是在同一個程式內部並行執行,因此會對相同的記憶體空間進行併發讀寫操作。這可能是在單線程程式中從來不會遇到的問題。其中的一些錯誤也未必會在單CPU機器上出現,因為兩個線程從來不會得到真正的並行執行。然而,更現代的電腦伴隨著多核CPU的出現,也就意味著不同的線程能被不同的CPU核得到真正意義的並行執行。


       那麼,要開始Java併發之路,就要開始從java線程開始說起.
       本篇幅將是本系列博客的開山篇,也就是基礎線程的複習.

線程簡介

線程百科

    線程,有時被稱為輕量級進程(Lightweight Process,LWP),是程式執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共用進程所擁有的全部資源。

線程優點

資源利用率更好
程式設計在某些情況下更簡單
程式響應更快

線程代價

設計更複雜
上下文切換的開銷上升
增加資源消耗

線程的實現方式

       線程我們有不同的實現方式,生產環境中用到的也有所不同,那麼,我們先來通過Demo看一下每種實現方式的區別.

通過Thread 實現的線程

public class Demo1 {
    public static void main(String args[]) {
        Thread thread = Thread.currentThread();
        System.out.println("當前線程:" + thread);

        thread.setName("hyh thread");//修改線程名稱

        System.out.println("修改名稱之後:" + thread);

        try {
            for (int a = 5; a > 0; a--) {
                System.out.println(a);

                thread.sleep(1000);
            }
        } catch (Exception e) {
            System.out.println("出現異常");
        }
    }

通過集成Runnable介面實現

Demo2.class 清單:

public class Demo2 implements Runnable {

    Thread t;

    //空構造函數
    Demo2() {
        t = new Thread(this, "測試線程");
        System.out.println("子線程" + t);
        t.start();
    }

    public void run() {
        try {
            for (int a = 5; a > 0; a--) {
                System.out.println("子線程" + a);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("異常");
        }
        System.out.println("退出子線程");
    }
}

/**
 * 主類
 */
class ThreadDemo {
    public static void main(String args[]) {
        new Demo2();//創建一個新線程
        try {
            for (int i = 5; i > 0; i--) {
                System.out.println("主線程:" + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("主線程異常");
        }
        //主線程退出
        System.out.println("主線程退出");

    }
}

通過集成 Thread 重寫run方法實現

public class Demo3 extends Thread {
    public Demo3() {
        //創建新線程
        super("線程Demo");
        System.out.println("子線程:" + this);
        start();
    }

    @Override
    public void run() {
        try {
            for (int a = 5; a > 0; a--) {
                System.out.println("子線程:" + a);
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            System.out.println("子程式異常");
        }
    }

}

class MasterThread {
    public static void main(String args[]) {
        new Demo3();//創建新線程

        try {
            for (int i = 5; i > 0; i--) {
                System.out.println("主線程:" + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("主程式異常");
        }
        System.out.println("主程式退出...");
    }
}

三個線程的實現

在日常生產中,使用線程可以通過實現Runnable介面.下麵我們通過該方法實現簡單的三個線程Demo

結構: 創建一個Demo4類,另外一個主類MultThreadDemo.
清單:

 public class Demo4 implements Runnable {
 //全局變數
    String name;
    Thread thread;

    //構造器
    public Demo4(String th) {
        name = th;
        thread = new Thread(this, name);
        System.out.println("新線程" + thread);
        //開始線程
        thread.start();
    }

    //重寫run方法
    public void run() {
        try {
            for (int a = 5; a > 0; a--) {
                System.out.println(name + ":" + a);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("異常");
        }
        System.out.println(name + "線程結束");
    }
}

/**
 * 測試類
 *
 * @author hyh
 */
class MultThreadDemo {

    public static void main(String[] args) {
        //創建三個線程
        Demo4 thread_1 = new Demo4("線程一");
        Demo4 thread_2 = new Demo4("線程二");
        Demo4 thread_3 = new Demo4("線程三");
        //查看狀態
        System.out.println("線程一狀態:" + thread_1.thread.isAlive());
        System.out.println("線程二狀態:" + thread_2.thread.isAlive());
        System.out.println("線程三狀態:" + thread_3.thread.isAlive());

        try {
            System.out.println("等待其他線程結束");
            //使用join確保主線程最後運行
            thread_1.thread.join();
            thread_2.thread.join();
            thread_3.thread.join();
        } catch (InterruptedException e) {
            System.out.println("線程異常");

        }
        //查看狀態
        System.out.println("線程一:" + thread_1.thread.isAlive());
        System.out.println("線程二:" + thread_2.thread.isAlive());
        System.out.println("線程三:" + thread_3.thread.isAlive());
    }
}

到此,開山Demo完成.
本文源碼Github地址:
https://github.com/hanyahong/com-hanyahong-blog/tree/master/com-hanyahong-thread-1/src/main/java/com/hyh/thread

思考:進程與線程的比較

進程
資源分配的基本單位。
所有與該進程有關的資源,都被記錄在進程式控制制塊PCB中。
進程處理機的調度單位,擁有完整的虛擬地址空間。當進程發生調度時,不同的進程擁有不同的虛擬地址空間,而同一進程內的不同線程共用同一地址空間。
線程與資源分配無關,屬於某一個進程,並與其他線程共用進程資源。
線程只由相關堆棧(系統棧或用戶棧)寄存器和線程式控制製表TCB組成。寄存器可被用來存儲線程內的局部變數,但不能存儲其他線程的相關變數。
進程在多線程中,進程不是一個可執行的實體。

兩者比較:
調度和切換:線程上下文切換比進程上下文切換要快得多。
通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變數)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。
地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共用。某進程內的線程在其它進程不可見。

(本篇完)
WeChat: wixf150
原創文章,轉發請註明出處:http://www.cnblogs.com/hyhnet/p/6250264.html
訪問獨立站點,獲得更好用戶體驗:http://www.hanyahong.com



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在《ASP.NET Core應用的錯誤處理[1]:三種呈現錯誤頁面的方式》中,我們通過幾個簡單的實例演示瞭如何呈現一個錯誤頁面,這些錯誤頁面的呈現分別由三個對應的中間件來完成,接下來我們將對這三個中間件進行詳細介紹。在開發環境呈現的異常頁面是通過一個類型為DeveloperExceptionPage... ...
  • 2009 年我讀了李笑來老師的《把時間當朋友》,知識了柳比歇夫的時間記錄法。當時激動壞了,馬上動手實踐起來。一開始的時候,是用一個小本子,走到哪兒都帶著。完成一件事,就記錄一下花費的時間。這樣的做法持續了一周多的時間,我發現每天浪費在 Google Reader 上的時間大幅度減少了。那個時候,我使 ...
  • 什麼是Servlet?① Servlet就是JAVA 類② Servlet是一個繼承HttpServlet類的類③ 這個在伺服器端運行,用以處理客戶端的請求 Servlet相關包的介紹--javax.servlet.* :存放與HTTP 協議無關的一般性Servlet 類;--javax.servl ...
  • 直接插入排序是將一個記錄插入到已經排好序的有序表中,從而得到一個新的記錄數加1的有序表。 下麵的代碼中會先假設數組的第一個元素是已經拍好序的有序表,然後從第二個元素開始遍歷剩下的元素。 所以呢,第一個for迴圈是遍歷待插入的元素,第二個for迴圈是遍歷被插入的有序表,並將待插入元素與有序表的元素比較 ...
  • 參考 http://www.cnblogs.com/chengmo/archive/2010/10/02/1841355.html 問題:bash怎麼提取字元串的最後一位?例如python中string[-1]就是python字元串最後一位。 echo ${PATH:((${#PATH} - 1)) ...
  • RSA.h #ifndef _RSA_H #define _RSA_H #include #include #include /* 密鑰產生: 1.隨機選定兩個大素數p, q. 2.計算公鑰和私鑰的公共模數 n = pq . 3.計算模數n的歐拉函數 φ(n) . 4.選定一個正整數e, 使1 e,... ...
  • SHA-1.cpp TEST.cpp ...
  • if __name__== "__main__" 的意思(作用)python代碼復用 轉自:大步's Blog http://www.dabu.info/if-__-namelxx_-main__-mean-function-python-code-reuse.html 有人在學習python腳本時 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...