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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

多线程启动定时器 会等待上一次执行完成?_Java多线程

發布時間:2025/3/15 java 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程启动定时器 会等待上一次执行完成?_Java多线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

進程和線程的區別

進程:操作系統應用程序。占用系統的 cpu 和內存線程:是進程更小的執行單元。一個進程可以有多個線程。線程與線程之間是相互獨立的,但是是要共用進程的資源。區別:每個進程都需要操作系統為其分配獨立的內存地址空間,而同一進程中的所有線程在同一塊地址空間中,這些線程可以共享數據,因此線程間的通信比較簡單,消耗的系統開銷也相對較小。

Thread 線程類

構造方法

Thread?thread?=?new?Thread();
Thread?thread?=?new?Thread(線程對象,"線程名字");

靜態方法

"查看線程最大級別":Thread.MAX_PRIORITY

"查看線程最小級別":Thread.MIN_PRIORITY

"查看線程默認級別":Thread.NORM_PRIORITY

常用方法

"讓線程開始執行":thread.start();??"自動調用線程的run()方法"

"返回線程的名字":thread.getName();

"返回線程的優先級":thread.getPriority();

"等待線程死亡":thread.join();
"等待線程死亡":thread.join(毫秒);

"給線程設置名字":thread.setName(名字);

"讓線程睡眠":thread.sleep(毫米數);
"當前線程讓出強占cpu的機會??自己馬上處于就緒狀態":thread.yield();

線程狀態

  • 新建狀態(New):使用new 關鍵字創建線程對象,僅僅被分配了內存
  • 就緒狀態(Ready):線程對象被創建后,等待它的 start 方法被調用,以獲得 CPU 的使用權
  • 運行狀態(Running)執行 run 方法,此時的線程的對象正占用 CPU
  • 睡眠狀態(Sleeping)調用 sleep 方法,線程被暫停,睡眠時間結束后,線程回到就緒狀態,睡眠狀態的線程不占用 CPU
  • 死亡狀態(Dead)run 方法執行完畢后,線程進入死亡狀態
  • 阻塞狀態(Blocked):線程由于某些事件(如等待鍵盤輸入)放棄 CPU,暫停運行,直到線程重新進入就緒狀態,才有機會轉到運行狀態

創建多線程的方法

繼承 Thread 類

實現步驟:

  • 創建一個 Thread 類的子類
  • 在 Thread 類的子類中重寫 Thread 類中的 run 方法,設置線程任務
  • 創建 Thread 類的子類對象
  • 調用 Thread 類中的方法 start 方法,開啟新的線程,執行 run 方法
  • public?class?MyThread?extends?Thread?{
    ????//?重新run方法就是創建了多線程
    ????@Override
    ????public?void?run()?{
    ????????//?放需要執行的代碼
    ????}

    ????//?使用
    ????public?static?void?main(String[]?args)?{
    ????????MyThread?et1?=?new?MyThread();
    ????????//?使用start方法執行
    ????????et1.start();
    ????}
    }

    實現 Runnable+Thread 類的帶參構造

    實現步驟:

  • 創建一個 Runnable 接口的實現類
  • 在實現類中重寫 Runnable 接口的 run 方法,設置線程任務
  • 創建一個 Runnable 接口的實現類對象
  • 創建 Thread 類對象,構造方法中傳遞 Runnable 接口的實現類對象
  • 調研 Thread 類中的 start 方法,開啟新的線程執行 run 方法
  • 實現 Runnable 接口創建多線程程序的好處:

  • 避免了單繼承的局限性,一個類只能繼承一個類,類繼承了 Thread 類就不能繼承其他的類,實現了 Runnable 接口,還可以繼承其他的類,實現其他的接口
  • 增強了程序的擴展性,降低了程序的耦合性(解耦),實現 Runnable 接口的方式,把設置線程任務和開啟新線程進行了分離(解耦)
  • public?class?MyRunnable?implements?Runnable{
    ????//?實現run方法
    ????@Override
    ????public?void?run()?{
    ????????//?放需要執行的代碼
    ????}
    ????//?使用
    ????public?static?void?main(String[]?args)?{
    ????????//?用Runnable的接口實現類的實例作為Thread的target
    ????????Thread?t1?=?new?Thread(new?MyRunnable());
    ????????//?調用
    ????????t1.start();
    ????}
    }

    實現 Callable+Future 模式

    public?class?CallableTest?{
    ????public?static?void?main(String[]?args)?throws?Exception?{
    ????????Callable?call?=?new?Callable()?{@Overridepublic?Integer?call()?throws?Exception?{//?需要執行的代碼//?返回值為Integerreturn?1;
    ????????????}
    ????????};//?Future就是對于具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果//?FutureTask類實現了RunnableFuture接口,RunnableFuture繼承了Runnable接口和Future接口
    ????????FutureTask?task?=?new?FutureTask<>(call);
    ????????Thread?t?=??new?Thread(task);
    ????????t.start();
    ????}
    }

    匿名內部類

    匿名內部類作用:簡化代碼

  • 把子類繼承父類,重寫父類的方法,創建子類對象合一步完成
  • 把實現類實現類接口,重寫接口中的方法,創建實現類對象合成一步完成
  • 匿名內部類的最終產物:子類/實現類對象,而這個類沒有名字
  • public?class?App?{
    ????public?static?void?main(String[]?args){
    ????????//?第一個方法,使用Runnable的方式
    ????????new?Thread(new?Runnable()?{
    ????????????@Override
    ????????????public?void?run()?{
    ????????????????//?需要執行的代碼
    ????????????}
    ????????}).start();

    ????????//?第二個方法
    ????????new?Thread(){
    ????????????@Override
    ????????????public?void?run(){
    ????????????????//?需要執行的代碼
    ????????????}
    ????????}.start();
    ????}
    }

    java.util.Timer 工具類

    public?class?TimerTest?{
    ????public?static?void?main(String[]?args)?throws?Exception?{
    ?????????//?啟動定時器線程,并在10000毫秒后執行TimerTask實例的run方法,每隔3000毫秒執行一次
    ????????new?Timer().schedule(new?TimerTask()?{
    ????????????@Override
    ????????????public?void?run()?{
    ????????????????//?需要執行的代碼
    ????????????}
    ????????},?10000,3000);
    ????}
    }

    java.util.concurrent.Executors 工具類

    public?class?ThreadPoolTest?{
    ????public?static?void?main(String[]?args)?{
    ????????//?創建線程池,10個
    ????????//?通過java.util.concurrent.ExecutorService接口對象來執行任務
    ????????//?該接口對象通過工具類java.util.concurrent.Executors的靜態方法來創建
    ????????ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);
    ????????while(true)?{
    ????????????threadPool.execute(new?Runnable()?{?//?提交多個線程任務,并執行
    ????????????????@Override
    ????????????????public?void?run()?{
    ????????????????????//?需要執行的代碼
    ????????????????}
    ????????????});
    ????????}
    ????}
    }

    線程同步方法

    同步代碼塊

    synchronized(互斥鎖)把代碼包裹起來,必須是同一把鎖注意:

  • 通過代碼塊中的鎖對象,可以使用任意的對象
  • 但是必須保證多個線程使用的鎖對象是同一個
  • 鎖對象作用:把同步代碼塊鎖住,只讓一個線程在同步代碼塊中執行
  • synchronized鎖定的是一個對象,不是代碼塊
  • 一個synchronized代碼塊是原子操作
  • synchronized的鎖是可重入的,即當前線程內,一個同步方法調用另一個同步方法或者子類同步方法調用父類同步方法,是可以再次獲得鎖
  • synchornized("鎖"){
    ????"出現線程安全的邏輯"
    }

    同步方法

    • 在方法的定義上面加synchronized 關鍵字
    "這里鎖定的是當前對象"
    public?synchronized?void?sale()?{"對象鎖?(必須是同一把鎖?saleWindow)"
    ?if?(tickets?<=?30)?{
    ??System.out.println(Thread.currentThread().getName()?+?"賣了第"?+?tickets?+?"張");//?獲得當前線程的名稱
    ??tickets++;
    ?}
    ?try?{
    ??Thread.sleep(400);
    ?}?catch?(InterruptedException?e)?{
    ??e.printStackTrace();
    ?}
    }
    //?等同于上面的鎖方法
    private?Object?o?=?new?Object();
    private?int?count?=?1;
    public?void?sale2(){
    ????"上鎖"
    ????synchronized(o){
    ????????count++;
    ????}
    }
    • 鎖定靜態方法
    private?int?count?=?1;
    //?這里相當于synchronized(T.class)
    //?因為在靜態方法中沒有this
    public?synchronized?static?void?m(){
    ????count++:
    }

    public?static?void?n(){
    ????synchronized(T.class){
    ????????count++;
    ????}
    }
    • 可重入鎖
    //?在同一個線程內獲得鎖后可以再獲得一次
    synchronized?void?t1(){
    ????//?執行邏輯
    ????t2();
    }

    synchronized?void?t2(){
    ????//?執行邏輯
    }

    Lock+ReentranLock 手動上鎖

    private?Integer?tickets?=?1;
    "創建一把鎖"
    private?Lock?lock?=?new?ReentrantLock();
    public?void?run()?{
    ?for?(int?i?=?1;?i?<=?100;?i++)?{
    ??"手動上鎖"
    ??lock.lock();

    ??if?(tickets?<=?100)?{
    ???tickets++;
    ??}
    ??try?{
    ???Thread.sleep(100);
    ??}?catch?(InterruptedException?e)?{
    ???e.printStackTrace();
    ??}
    ??"手動解鎖"
    ??lock.unlock();
    ?}
    }

    sleep、yield、join 和 wait

    • sleep 和 yield 都是 Thread 類的靜態方法,都會使當前處于運行狀態的線程放棄 CPU,但兩者的區別在于:
  • sleep 給其它線程運行的機會,但不考慮其它線程的優先級;但 yield 只會讓位給相同或更高優先級的線程
  • 當線程執行了 sleep 方法后,將轉到阻塞狀態,而執行了 yield 方法之后,則轉到就緒狀態
  • sleep 方法有可能拋出異常,而 yield 則沒有,在一般情況下,我們更建議使用 sleep 方法
    • join 方法用于等待其它線程結束,當前運行的線程可以調用另一線程的 join 方法,當前運行線程將轉到阻塞狀態,直至另一線程執行結束,它才會恢復運行
    • wait 方法是 Object 類的方法,讓當前線程等待,直到另一個線程調用該對象的 notify()方法或 notifyAll()方法才會執行,必須是鎖對象才能調用

    END

    往期推薦

    • SpringBoot

    • RocketMQ整合SpringBoot

    • Solr整合SpringBoot

    • Spring全家桶教程

    • 圖靈學院微服務教程

    總結

    以上是生活随笔為你收集整理的多线程启动定时器 会等待上一次执行完成?_Java多线程的全部內容,希望文章能夠幫你解決所遇到的問題。

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