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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java之初学线程

發(fā)布時(shí)間:2024/1/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java之初学线程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

線程

學(xué)習(xí)線程相關(guān)的筆記,前面寫過(guò)關(guān)于很多線程的使用,有興趣的可以去了解下

線程

概念理解

  • 并發(fā) : 指兩個(gè)或多個(gè)事件在同一個(gè)時(shí)間段內(nèi)發(fā)生(交替執(zhí)行)。
  • 并行 : 指兩個(gè)或多個(gè)事件在同一時(shí)刻發(fā)生(同時(shí)發(fā)生)。
  • 進(jìn)程 : 是指一個(gè)內(nèi)存中運(yùn)行的應(yīng)用程序,每個(gè)進(jìn)程都有一個(gè)獨(dú)立的內(nèi)存空間,一個(gè)應(yīng)用程序可以同時(shí)運(yùn)行多
    個(gè)進(jìn)程;進(jìn)程也是程序的一次執(zhí)行過(guò)程,是系統(tǒng)運(yùn)行程序的基本單位;系統(tǒng)運(yùn)行一個(gè)程序即是一個(gè)進(jìn)程從創(chuàng)
    建、運(yùn)行到消亡的過(guò)程。
  • 線程 : 進(jìn)程內(nèi)部的一個(gè)獨(dú)立執(zhí)行單元;一個(gè)進(jìn)程可以同時(shí)并發(fā)的運(yùn)行多個(gè)線程,可以理解為一個(gè)進(jìn)程便相當(dāng)
    于一個(gè)單 CPU 操作系統(tǒng),而線程便是這個(gè)系統(tǒng)中運(yùn)行的多個(gè)任務(wù)(一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程可以有多個(gè)線程)。

    線程和進(jìn)程的區(qū)別 :

    1.進(jìn)程:有獨(dú)立的內(nèi)存空間,進(jìn)程中的數(shù)據(jù)存放空間(堆空間和棧空間)是獨(dú)立的,至少有一個(gè)線程。
    2.線程:堆空間是共享的,棧空間是獨(dú)立的,線程消耗的資源比進(jìn)程小的多。

多線程的原理

從圖中可以看出,線程的啟動(dòng)實(shí)際上是開(kāi)辟了新的空間,這樣的話jvm就可以在U盾謳歌棧之間相互切換,這個(gè)就是多線程的原理.

Runnable接口

Runnable是多線程的祖宗類,多線程都間接或直接的實(shí)現(xiàn)了這個(gè)接口.內(nèi)部只有run方法,所以也可以看出run方法時(shí)多線程的核心.

Thread類

先了解一下Thread類的內(nèi)部方法:

構(gòu)造方法:

  • public Thread() :分配一個(gè)新的線程對(duì)象。
  • public Thread(String name) :分配一個(gè)指定名字的新的線程對(duì)象。
  • public Thread(Runnable target) :分配一個(gè)帶有指定目標(biāo)新的線程對(duì)象。
  • public Thread(Runnable target,String name) :分配一個(gè)帶有指定目標(biāo)新的線程對(duì)象并指定名字。

常用方法:

  • public String getName() :獲取當(dāng)前線程名稱。
  • public void start() :導(dǎo)致此線程開(kāi)始執(zhí)行; Java虛擬機(jī)調(diào)用此線程的run方法。
  • public void run() :此線程要執(zhí)行的任務(wù)在此處定義代碼。
  • public static void sleep(long millis) :使當(dāng)前正在執(zhí)行的線程以指定的毫秒數(shù)暫停(暫時(shí)停止執(zhí)行)。
  • public static Thread currentThread() :返回對(duì)當(dāng)前正在執(zhí)行的線程對(duì)象的引用。

使用Thread來(lái)創(chuàng)建線程

  • 創(chuàng)建Thread類的子類
  • 在Thread類的子類中重寫run方法,設(shè)置線程任務(wù)
  • 創(chuàng)建Thread類的子類
  • 調(diào)用Thread類的方法start方法,開(kāi)啟新的線程,執(zhí)行run方法.(這需要注意,是調(diào)用start方法,而不是直接調(diào)用run方法)
  • void start() :導(dǎo)致此線程開(kāi)始執(zhí)行; Java虛擬機(jī)調(diào)用此線程的run方法。結(jié)果是兩個(gè)線程并發(fā)執(zhí)行,當(dāng)前線程(main)
    和另一個(gè)線程(創(chuàng)建的新線程,執(zhí)行其run方法),多次啟動(dòng)一個(gè)線程是非法的.特別當(dāng)線程已經(jīng)結(jié)束后,不能重新啟動(dòng).java程序
    是搶占式調(diào)度,哪個(gè)線程優(yōu)先級(jí)高,哪個(gè)線程先執(zhí)行;同一個(gè)優(yōu)先級(jí),隨機(jī)選擇一個(gè).

    獲取線程名稱

    獲取線程的名稱有兩種方法:

    • 使用getName()獲取線程名稱,這個(gè)需要使用Thread類的子類對(duì)象來(lái)調(diào)用.
    • 使用Thread.currentThread().getName()獲取線程名稱(推薦使用)
    設(shè)置線程名稱

    設(shè)置線程的名稱也有兩種方式:

    • 使用setName()方法設(shè)置線程名稱,也是需要Thread類或者子類的對(duì)象調(diào)用.
    • 使用構(gòu)造方法,可以使用有參構(gòu)造來(lái)設(shè)置線程名稱.

    Runnable接口

  • 定義一個(gè)類,實(shí)現(xiàn)Runnable接口(任務(wù)類).
  • 重寫Runnable的run方法
  • 創(chuàng)建任務(wù)類對(duì)象
  • 創(chuàng)建線程類對(duì)象,并將任務(wù)對(duì)象參數(shù)作為參數(shù)進(jìn)行傳遞
  • 使用線程類對(duì)象調(diào)用start方法啟動(dòng)線程.

    這個(gè)過(guò)程中需要注意的是第四步,需要使用public Thread(Runnable target) :分配一個(gè)帶有指定目標(biāo)新的線程對(duì)象。
    public Thread(Runnable target,String name) :分配一個(gè)帶有指定目標(biāo)新的線程對(duì)象并指定名字。這兩個(gè)構(gòu)造方法.

  • 創(chuàng)建線程的方式

    • 實(shí)現(xiàn)Runnable接口

      /*** 使用實(shí)現(xiàn)Runnable接口實(shí)現(xiàn)多線程** @author WZLOVE* @create 2018-07-16 19:46*/public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}}
    • 繼承Thread類

      /*** 使用繼承實(shí)現(xiàn)多線程** @author WZLOVE* @create 2018-07-16 19:47*/public class MyThread extends Thread{public MyThread() {}public MyThread(String name) {super(name);}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName() + ":" + i);}}}
    • 不同的方法實(shí)現(xiàn)多線程,創(chuàng)建對(duì)象使用的方式也不同:

      /*** @author WZLOVE* @create 2018-07-16 19:45*/public class ThreadDemo {public static void main(String[] args) {// 繼承創(chuàng)建對(duì)象相對(duì)簡(jiǎn)單MyThread mt = new MyThread("繼承");mt.start();// 實(shí)現(xiàn)接口創(chuàng)建對(duì)象// 創(chuàng)建自定義類對(duì)象MyRunnable mr = new MyRunnable();// 創(chuàng)建線程對(duì)象Thread thread = new Thread(mr,"實(shí)現(xiàn)接口");thread.start();}}

      注意點(diǎn):

      1.實(shí)際上,Thread類也實(shí)現(xiàn)了Runnable接口.
      2.所有的多線程代碼都在run方法里面
      3.所有的多線程代碼都是通過(guò)運(yùn)行Thread的start()方法來(lái)運(yùn)行的
      4.Runnable對(duì)象僅僅作為Thread對(duì)象的target,Runnable實(shí)現(xiàn)類里包含的run()方法僅作為線程執(zhí)行體。
      而實(shí)際的線程對(duì)象依然是Thread實(shí)例,只是該Thread線程負(fù)責(zé)執(zhí)行其target的run()方法。

    實(shí)現(xiàn)Runnable接口與繼承Thread類的不同點(diǎn)

    使用接口比類是更有優(yōu)勢(shì)的:

    • 可以避免java中的單繼承的局限性。
    • 增加程序的健壯性,實(shí)現(xiàn)解耦操作,代碼可以被多個(gè)線程共享,代碼和線程獨(dú)立(任務(wù)類和線程類進(jìn)行分離,解耦)。
    • 但是實(shí)現(xiàn)接口不能直接使用Thread類的方法,但是可以通過(guò)獲取當(dāng)前線程對(duì)象進(jìn)行調(diào)用方法.
    • 適合多個(gè)相同的程序代碼的線程去共享同一個(gè)資源。
    • 線程池只能放入實(shí)現(xiàn)Runable或Callable類線程,不能直接放入繼承Thread的類。

    線程的安全問(wèn)題的產(chǎn)生

    線程的安全問(wèn)題的產(chǎn)生是由于多個(gè)線程對(duì)共享資源的訪問(wèn).簡(jiǎn)單的說(shuō)線程安全問(wèn)題都是由全局變量及靜態(tài)變量引起的。
    若每個(gè)線程中對(duì)全局變量、靜態(tài)變量只有讀操作,而無(wú)寫操作,一般來(lái)說(shuō),這個(gè)全局變量是線程安全的;
    若有多個(gè)線程同時(shí)執(zhí)行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。
    買電影票的例子(出現(xiàn)安全問(wèn)題,運(yùn)行一下):

    package com.wzlove.thread.movie;/*** 票數(shù)的任務(wù)類** @author WZLOVE* @create 2018-07-17 14:35*/ public class TicketRunnableImpl implements Runnable{/*** 定義共享資源*/private int ticket = 100;@Overridepublic void run() {while (true){if(ticket > 0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在賣第"+ ticket -- + "張票");}}} }package com.wzlove.thread.movie;/*** 多線程安全問(wèn)題的測(cè)試** @author WZLOVE* @create 2018-07-17 14:37*/ public class MovieDemo {public static void main(String[] args) {// 創(chuàng)建任務(wù)類對(duì)象TicketRunnableImpl ticketRunnable = new TicketRunnableImpl();// 創(chuàng)建線程對(duì)象Thread t1 = new Thread(ticketRunnable,"窗口1");Thread t2 = new Thread(ticketRunnable,"窗口2");Thread t3 = new Thread(ticketRunnable,"窗口3");// 開(kāi)始線程t1.start();t2.start();t3.start();} }

    上面的情況就會(huì)出現(xiàn)線程安全問(wèn)題.

    線程的安全問(wèn)題的解決

    使用同步解決線程的安全問(wèn)題.

    • 同步代碼塊
    • 同步方法
    • lock鎖機(jī)制

    1.同步代碼塊

    格式 :

    // 同步對(duì)象可一是任意對(duì)象,推薦使用thissynchronized(同步對(duì)象){可能出現(xiàn)同步問(wèn)題的代碼}

    鎖對(duì)象可以是任意對(duì)象,但是鎖對(duì)象必須唯一.

    2.同步方法

    格式:

    // 同步方法也是有鎖對(duì)象的,也就是當(dāng)前對(duì)象this修飾符 synchronized 返回值類型 方法名(參數(shù)列表){可能出現(xiàn)同步問(wèn)題的代碼}

    需要注意的是靜態(tài)同步方法內(nèi)的同步鎖不是this(因?yàn)殪o態(tài)代碼的執(zhí)行在this之前產(chǎn)生),而是類的字節(jié)碼對(duì)象,也就是(類名.class)

    3.Lock鎖機(jī)制

    • public void lock() :加同步鎖。
    • public void unlock() :釋放同步鎖。

    使用步驟:

  • 創(chuàng)建ReentrantLock的對(duì)象
  • 在使用共享資源前使用lock方法進(jìn)行加鎖
  • 在使用共享資源結(jié)束后使用unlock方法釋放同步鎖
  • 線程狀態(tài)的概述

    線程狀態(tài)導(dǎo)致?tīng)顟B(tài)發(fā)生條件
    new()新建線程剛被創(chuàng)建,但是并未啟動(dòng)。還沒(méi)調(diào)用start方法。
    Runnable(可運(yùn)行)線程可以在java虛擬機(jī)中運(yùn)行的狀態(tài),可能正在運(yùn)行自己代碼,也可能沒(méi)有,這取決于操 作系統(tǒng)處理器。
    Blocked(鎖阻塞)當(dāng)一個(gè)線程試圖獲取一個(gè)對(duì)象鎖,而該對(duì)象鎖被其他的線程持有,則該線程進(jìn)入Blocked狀 態(tài);當(dāng)該線程持有鎖時(shí),該線程將變成Runnable狀態(tài)。
    Waiting(無(wú)限等待)一個(gè)線程在等待另一個(gè)線程執(zhí)行一個(gè)(喚醒)動(dòng)作時(shí),該線程進(jìn)入Waiting狀態(tài)。進(jìn)入這個(gè) 狀態(tài)后是不能自動(dòng)喚醒的,必須等待另一個(gè)線程調(diào)用notify或者notifyAll方法才能夠喚醒。
    Timed Waiting(計(jì)時(shí)等待)同waiting狀態(tài),有幾個(gè)方法有超時(shí)參數(shù),調(diào)用他們將進(jìn)入Timed Waiting狀態(tài)。這一狀態(tài) 將一直保持到超時(shí)期滿或者接收到喚醒通知。帶有超時(shí)參數(shù)的常用方法有Thread.sleep 、 Object.wait。
    Teminated(被終止)因?yàn)閞un方法正常退出而死亡,或者因?yàn)闆](méi)有捕獲的異常終止了run方法而死亡。

    狀態(tài)圖:

    等待喚醒機(jī)制

    Object類中的四個(gè)方法:

    • wait() : 使線程處于等待狀態(tài),等待著其他的線程喚醒
    • wait(long millis) : 使線程處于等待狀態(tài), 等待著其他的線程喚醒/等待時(shí)間到達(dá)
    • notify() : 喚醒其他的單個(gè)等待的線程
    • notifyAll() : 喚醒其他的所有等待的線程

    sleep()與wait()

    • sleep:Thread類中的靜態(tài)方法,休眠指定的時(shí)間,在指定時(shí)間后自動(dòng)喚醒,不回釋放鎖對(duì)象
    • wait : Object類中的方法,無(wú)限等待,等待其他線程的喚醒,必須釋放鎖對(duì)象

    轉(zhuǎn)載于:https://www.cnblogs.com/wadmwz/p/9325466.html

    總結(jié)

    以上是生活随笔為你收集整理的java之初学线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。