Java基礎(四)線程快速瞭解

来源:https://www.cnblogs.com/zhaof/archive/2018/07/07/9278865.html
-Advertisement-
Play Games

開始整理線程之前,之前有個命令忘記整理了,先整理一下jar命令的使用 Jar包 其實可以理解是java的壓縮包方便使用,只要在classpath設置jar路徑即可資料庫驅動,ssh框架等都是以jar包體現的 打包方式一:將指定的class文件打入到jar包中jar cvf xxx.jar Xxx.c ...


開始整理線程之前,之前有個命令忘記整理了,先整理一下jar命令的使用

 

Jar包

其實可以理解是java的壓縮包
方便使用,只要在classpath設置jar路徑即可
資料庫驅動,ssh框架等都是以jar包體現的

打包方式一:將指定的class文件打入到jar包中
jar cvf xxx.jar Xxx.class yyy.class

打包方式二:將某個目錄下的所有文件打入到jar包中
jar cvf xxx.jar -C xxx/.

查看jar文件:
jar -tf xxx.jar

運行jar包中的類:
java -cp xxx.jar xx.xx.xx(完整的類名)

常用的jar命令參數:
c:創建壓縮文件
f:指定存檔名稱
v:顯示詳細信息
m:加入自定義清單

指定清單文件(xxx.jar/META-INF/MNIFEST.MF)的入口類
jar cvfe classess.jar com.zhaofan.PackagDemo1 classes/.
這樣我們就可以通過java -jar xxx.jar直接執行

線程

進程:運行時概念,運行的應用程式
線程:應用程式內部併發執行的代碼段,共用記憶體

這裡幾個關鍵詞
yield: 放棄cpu搶占權
join:等待指定的線程執行完
sleep:靜態方法,讓線程休眠毫秒數
daemo:守護線程

最簡單的線程代碼:

package study_java.ex9;

public class ThreadDemo1 {
    public static void main(String[] args){
        Mythread t1 = new Mythread();
        t1.start();
    }
}

class Mythread extends Thread{
    public void run(){
        while (true){
            System.out.println("MyThread");
        }

    }
}

join的一個簡單實用例子:

package study_java.ex9;

public class ThreadDemo2 {
    public static void main(String[] args){
        Player p1 = new Player("aa",5000);
        Player p2 = new Player("bb",8000);
        Player p3 = new Player("cc",2000);
        Player p4 = new Player("dd",3000);
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        try{
            p1.join();
            p2.join();
            p3.join();
            p3.join();
        }
        catch (Exception e){

        }


        System.out.println("人到了,開始玩游戲");
    }
}

class Player extends Thread{
    private String name;
    private int time;
    public Player(String name, int time){
        this.name = name;
        this.time = time;
    }
    public void run(){
        System.out.println("玩家:"+name + "出發了");
        try{
            Thread.sleep(time);
        }
        catch (Exception e){

        }
        System.out.println("玩家:"+name + "到了");


    }
}

守護線程的一個使用例子

package study_java.ex9;

import java.util.Date;

public class ThraedDemo3 {
    public static void main(String[] args){
        Room r1 = new Room("no1",15000);
        Waiter w1 = new Waiter();
        //w1.setDaemon(true); 設置守護線程
        r1.start();
        w1.start();
    }
}

class Room extends Thread{
    private String no;
    private int time;

    public Room(String no, int time){
        this.no = no;
        this.time = time;
    }

    public void run(){
        System.out.println("no" + "號房間正在唱歌");
        try{
            Thread.sleep(time);
        }
        catch (Exception e){

        }
        System.out.println("no" + "買單");
    }
}

class Waiter extends Thread{
    public Waiter(){
        this.setDaemon(true);
    }
    public void run(){
        while (true){
            System.out.println(new java.util.Date());
            try{
                Thread.sleep(1000);
            }
            catch (Exception e){

            }
        }
    }
}

任何一個對象都可以是鎖,信號燈,其實就是一個參照物
一個鎖的代碼例子:

package study_java.ex9;

public class ThreadDemo4 {
    public static void main(String[] args){
        Saler s1 = new Saler("a1");
        Saler s2 = new Saler("a2");
        s1.start();
        s2.start();
    }
}

class Saler extends Thread{
    //
    static Object lock = new Object();

    static int tickts = 100;
    private String name;
    public Saler(String name){
        this.name = name;
    }
    public void run(){
        while (true){
            int tick = getTickts();
            if (tick > 0){
                System.out.println(name+":"+ tick);
            }
            else {
                return;
            }
        }
    }
    // 取票
    public int getTickts(){
        synchronized (lock){
            int currTicket = tickts;
            tickts --;
            return currTicket;
        }
    }
}

還有一種方法是:

public static synchronized int getTickts(){
   int currTicket = tickts;
   tickts --;
   return currTicket;
}

這樣也能實現鎖的機制,但是註意這裡必須是static

我們整理一個新的寫法,把票池單獨寫出來

public class ThreadDemo2 {
    public static void main(String[] args){
        TicketPool pool = new TicketPool();
        Saler s1 = new Saler("s1",pool);
        Saler s2 = new Saler("s2",pool);
        s1.start();
        s2.start();
    }
}

// 票池
class TicketPool {
    private int tickets = 100;
    // 從票池取票
    public synchronized int getTickets(){
        int ticket = tickets;
        tickets -= 1;
        return ticket;
    }
}
// 售票員
class Saler extends Thread{
    private TicketPool pool = null;
    private String name;
    public Saler(String name, TicketPool tp){
        this.name = name;
        this.pool = tp;
    }
    public void run(){
        while (true){
            int no = pool.getTickets();
            if (no > 0 ){
                System.out.println(name + ":" + no);
            }
            else {
                return;
            }
        }
    }
}

兩個小的練習熟悉上面知識點的使用:
車過山洞的問題,山洞同時只允許一個車通過,現在有多輛車,不同的車通過的時間不同,代碼實現如下:

package study_java.ex11;

public class CarCave {
    public static void main(String[] args){
        Cave cave = new Cave();
        Car car1 = new Car(cave,10000,"奧迪");
        Car car2 = new Car(cave,8000,"賓士");
        Car car3 = new Car(cave,6000,"寶馬");
        Car car4 = new Car(cave,2000,"悍馬");
        car1.start();
        car2.start();
        car3.start();
        car4.start();

    }
}

class Cave{

    public synchronized void crossCar(Car car){
        try{
            System.out.println(car.name+":開始過山洞了");
            Thread.sleep(car.time);
            System.out.println(car.name+":開始出山洞了");
        }
        catch (Exception e){

        }


    }
}

class Car extends Thread{
    public Cave cave;
    public int time;
    public String name;

    public Car(Cave cave ,int time,String name){
        this.cave = cave;
        this.time = time;
        this.name = name;
    }
    public void run(){
        cave.crossCar(this);
    }
}

第二個小練習是我們經常遇到的場景,取票問題,現在有一個取票機,但是有五十個人要取票,實現代碼如下:

package study_java.ex11;

public class TicketDemo1 {
    public static void main(String[] args){
        TicketMachine m = new TicketMachine();
        for (int i=0;i<50;i++){
            new Person(m,"tom"+i).start();
        }
    }
}


// 取票機
class TicketMachine{
    private int ticketNo = 1;
    // 列印票號
    public synchronized int printTicktNo(){
        int currTicketNo = ticketNo;
        ticketNo ++;
        return currTicketNo;
    }
}

class Person extends Thread{
    private TicketMachine m;
    private String name;
    public Person(TicketMachine m,String name) {
        this.m = m;
        this.name = name;
    }
    public void run(){
        int no = m.printTicktNo();
        System.out.println(name+ ":" + no);
    }
}

生產者消費者模型

通過上面的知識點,寫一個生產者好消費者模型

package study_java.ex11;

import java.util.LinkedList;
import java.util.List;

public class PCDemo1 {
    public static void main(String[] args){
        MyList myList = new MyList();

        Productor p = new Productor(myList);
        Consumer c = new Consumer(myList);
        Consumer c2 = new Consumer(myList);
        Consumer c3 = new Consumer(myList);
        p.start();
        c.start();
        c2.start();
        c3.start();
    }

}

class MyList{
    private int Max = 100;
    private List<Integer> list = new LinkedList<Integer>();
    public  void addLast(Integer i){
        while (true){
            synchronized (list){
                if (list.size() < Max){
                    list.add(i);
                    return;
                }
            }
        }


    }
    public  Integer removeFirst(){
        while (true){
            synchronized (list){
                if(!list.isEmpty()){
                    return list.remove(0);
                }
            }
        }
    }
}

class Productor extends Thread{
    private MyList myList;
    public Productor(MyList myList){
        this.myList = myList;
    }
    public void run(){
        int i = 1;
        while (true){
            myList.addLast(new Integer(i));
            System.out.println("生產者生產了"+i+"號");
            i++;
        }
    }
}

class Consumer extends Thread{
    private MyList myList;
    public Consumer(MyList myList){
        this.myList = myList;
    }
    public void run(){
        while (true){
            int no = myList.removeFirst();
            System.out.println("消費者消費了"+no+"號");
        }
    }
}

生產者消費者而改進版本:

package study_java.ex11;

import java.util.LinkedList;
import java.util.List;

public class PCDemo5 {
    public static void main(String[] args){
        Pool pool = new Pool();
        Producter p1 = new Producter(pool);
        Consumer c1 = new Consumer(pool);
        p1.start();
        c1.start();

    }
}

class Pool{
    private List<Integer> list = new LinkedList<Integer>();
    private int Max = 100;
    public void addLast(int n){
        synchronized (this){
            while (list.size() >= Max){
                try{
                    this.wait();
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
            list.add(new Integer(n));

            this.notifyAll();
        }
    }
    public int remove(){
        synchronized (this){
            while (list.size() == 0){
                try{
                    this.wait();
                }
                catch (Exception e){
                    e.printStackTrace();
                }

            }
            int no = list.remove(0);

            this.notifyAll();
            return no;
        }
    }

}

// 生產者
class Producter extends Thread{
    private Pool pool;
    static int i = 1;
    public Producter(Pool pool){
        this.pool = pool;
    }
    public void run(){
        while (true){
            pool.addLast(i++);
            System.out.println("生產者生產了"+i+"號");
        }
    }

}


// 消費者
class Consumer extends Thread{
    private Pool pool;
    public Consumer(Pool pool){
        this.pool = pool;
    }
    public void run(){
        while (true){
            int no = pool.remove();
            System.out.println("消費者消費了"+no+"號");
        }
    }

}

wait():讓當前線程進入到鎖對象的等待隊列里,同時釋放鎖旗標。這個方法是當前鎖對象的方法
wait這裡還可以添加參數wait(int n) :等待指定的時間片,等待隊列中的線程最多等待n毫秒

notify():這個方法是當前鎖對象的方法,註意這裡並不會釋放鎖
notifyAll():通知等待隊列中的所有線程都可以搶占cpu運行,通知需要獲得對象的監控權

sleep:當前CPU的搶占權,和鎖對象的監控權無關。
Thread.currentThread().getName():獲取當前線程名字
Thread.currentThread().setName():設置當前線程名字

priority:1-10從低到高,預設是5
Thread.currentThread().getPriority():設置當前線程優先順序

線程狀態:
BLOCKED: 阻塞
NEW:新建
RUNNABL:執行
TERMINATED:已經終止
TIMED_WAITING:限時等待
WAITING:等待

 

 

 

創建一個線程的另外一種方式:
實現Runnable介面
1. 子類覆蓋介面中的run方法
2. 通過Thread類創建線程,並將實現了Runnable介面的子類對象作為參數傳遞給Thread類的構造函數
3. Thread類對象調用start方法開啟線程

代碼例子如下:

package study_java.ex11;

public class RunnableDemo1 {
    public static void main(String[] args){
        MyRunnabl m = new MyRunnabl();
        new Thread(m).start();
    }
}

class MyRunnabl implements Runnable{
    public void run(){
        System.out.println("hello world");
    }
}

同步(synchronized)

synchronized(對象)
{
需要同步的代碼
}
同步的特點:
同步的前提是:
需要兩個或者兩個以上的線程
多個線程使用的同一個鎖

同步的弊端:
當線程相當多時,因為每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程式的額運行效率

 


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

-Advertisement-
Play Games
更多相關文章
  • 基於React的一個簡單Todo-list 先賭為快:線上DEMO,感覺還不錯點一下star -_- ~ 源碼地址: 一、已經完成的功能 1、新增選項(預設未完成) 2、完成狀態可以切換 3、當前選項可以刪除 4、全部選項選中狀態切換 5、全部個數,完成個數,未完成個數實時讀取 6、刷新狀態不變 7 ...
  • 1. 使用Set ES6 提供了新的數據結構Set, 它類似數組,和C++中的set容器一樣,它成員的值都是唯一的,沒有重覆的值;Set本身是一個構造函數,用來生成Set數據結構。 還有更簡單的方式 上面這種方式在於Array.from方法可以將Set結構轉化為數組。如果你還覺得不過癮,那麼還有一種 ...
  • HTML5 標準事件 oninput 和 IE 專屬事件 onpropertychange 事件實時監聽input輸入框value的變化 ...
  • 本篇文章主要介紹設計模式中的單例模式使用。有經典餓漢式和飽漢式,也包含最優的單例模式的介紹使用。 ...
  • Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3121 Accepted Submission(s): 778 Problem Descript ...
  • Description Input 第1行包含5個整數,依次為 x_0,a,b,c,d ,描述小H採用的隨機數生成演算法所需的隨機種子。第2行包含三個整數 N,M,Q ,表示小H希望生成一個1到 N×M 的排列來填入她 N 行 M 列的棋盤,並且小H在初始的 N×M 次交換操作後,又進行了 Q 次額外 ...
  • Flask中的session cookie:是一種保存數據的格式,也可以看成是保存數據的一個“盒子”,伺服器返回cookie給瀏覽器(由伺服器產生),由瀏覽器保存在本地,下次再訪問此伺服器時瀏覽器就會自動將此cookie一起發送給伺服器。 session:也是一種保存數據的格式,也可以看成是保存數據 ...
  • 一、正則表達式簡介 正則表達式是一個特殊的字元序列,它能幫助你方便的檢查一個字元串是否與某種模式匹配。 Python 自1.5版本起增加了re 模塊,它提供 Perl 風格的正則表達式模式。 就其本質而言,正則表達式(或 RE)是一種小型的、高度專業化的編程語言, (在Python中)它內嵌在Pyt ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...