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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

闭关修炼(一)多线程

發布時間:2023/12/14 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 闭关修炼(一)多线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2021年,記得元旦快了樂~~


文章目錄

  • 線程與進程的區別
  • 多線程應用場景
  • 繼承方式創建多線程
    • 同步和異步的概念?
      • 同步
      • 異步
  • runnable接口創建多線程
  • 使用匿名內部類方式創建多線程
  • Callable方式創建多線程
  • 線程池方式創建多線程
  • 多線程常見API
    • getId()
    • getName()
    • sleep()
    • Thread.currentThread()
    • stop()
    • Thread()
  • 守護線程與非守護線程
    • 設置守護線程
  • 多線程運行狀態
  • join()方法作用
    • 面試題順序執行T1,T2,T3
  • 案例多線程分批處理數據


線程與進程的區別

  • 什么是應用程序?
    可以執行的軟件,在一個應用程序中,都會有一個進程。

  • 在進程中,程序代碼如何執行?
    在進程中,一定有一個主線程,java中的main

  • 什么是線程?
    進程中的一條執行順序/流程/路徑。

  • 什么是進程?
    進程中有多個不同的執行路徑,進程是線程的集合,是正在執行中的程序,任務管理器中可以看見進程。

  • 使用多線程的好處?
    提高程序效率。
    線程之間互不影響,因為線程都在自己獨立運行。
    一個進程可中有多個線程,提高程序效率,提高用戶體驗。

  • 注意事項
    多線程并不提高單路徑執行速度,而是多路徑同時進行提高程序效率。

多線程應用場景

  • 多線程下載
  • 爬蟲
  • ajax異步上傳
  • 分布式job,同一時刻執行多個任務調度
  • mq
  • 繼承方式創建多線程

    創建線程有5種方式

  • 繼承Thread類
  • runnable接口
  • 使用匿名內部類方式
  • callable
  • 線程池
  • 繼承Thread接口,重寫(override)run方法,run方法就是線程需要執行的代碼。

    class MyThread extends Thread{@Overridepublic void run() {for (int i =0 ; i< 30; i++){System.out.println(i);}} }

    啟動線程,實例化類,調用start方法,如果調用run方法還是單獨的執行run方法。

    public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();for (int i =31 ; i< 60; i++){System.out.println("main" + i);}}

    啟動多線程,代碼不會從上往下執行。

    同步和異步的概念?

    同步

    main函數中有方法①和方法②,每個方法都需要花費10秒時間,則需要20秒完成main函數。

    代碼從上往下執行,被稱為同步。

    同步中,main函數的方法之間存在依賴關系,存在執行順序,方法②等待方法①執行完畢后才能執行。

    也叫做單線程。

    異步

    可以理解為多線程,方法①和方法②同時執行,每個方法都需要花費10秒時間,則需要10秒完成main函數。提高程序效率,線程間獨立,互不影響。

    CPU調度時 異步中有執行權的概念,但在宏觀上看是同時進行的。

    runnable接口創建多線程

    創建類,實現runnable接口,重寫run方法

    class MyThread2 implements Runnable{public void run() {for (int i =0 ; i< 30; i++){System.out.println("run" + i);}} }

    啟動線程方式,接口作為參數傳遞給Thread類,調用start方法

    public static void main(String[] args) {MyThread2 myThread2 = new MyThread2();Thread thread = new Thread(myThread2);thread.start();}

    使用繼承方式創建線程還是使用runnable接口創建線程好?
    使用接口方式,開發面向接口編程,繼承后不能再繼承,接口可以。

    使用匿名內部類方式創建多線程

    什么是匿名內部類?
    沒有名稱的內部類。

    例子:

    abstract class Person{abstract void add(); } public static void main(String[] args) {Person person = new Person() {void add() {System.out.println("hello");}};person.add();}

    線程中也是類似,實例化Thread類,runnable接口使用匿名內部類進行實現

    public static void main(String[] args) {Thread thread = new Thread(new Runnable() {public void run() {System.out.println("Hello~");}});thread.start();}

    Callable方式創建多線程

    待更

    線程池方式創建多線程

    待更

    多線程常見API

    getId()

    獲取線程的id,id唯一

    class MyThread extends Thread{@Overridepublic void run() {for (int i =0 ; i< 30; i++){System.out.println(getId()+ "run" + i);}} }

    主線程id如何獲取?

    System.out.println(Thread.currentThread().getId());

    主線程id為1

    任何一個程序都會有一個主線程,本質也是一個線程。

    getName()

    獲取線程名稱

    System.out.println(Thread.currentThread().getName());

    主線程的name是main
    子線程名稱默認是Thread-0,Thread-1,Thread-2…

    sleep()

    暫停

    class MyThread extends Thread{@Overridepublic void run() {for (int i =0 ; i< 30; i++){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getId()+ "run" + i);}} }

    Thread.currentThread()

    獲取當前線程,在用Runnable接口的時候需要用這種方式獲取當前線程。

    stop()

    不安全,已過時

    class MyThread extends Thread{@Overridepublic void run() {for (int i =0 ; i< 30; i++){if (i==5){stop();}System.out.println(getId()+ "run" + i);}} }

    Thread()

    new Thread(new Runnable() {public void run() {System.out.println(1);}}, "線程名");

    守護線程與非守護線程

    什么是守護線程?
    和main函數相關。
    守護線程和主線程一起銷毀。
    如gc線程,垃圾回收機制中的單獨的一個線程,專門用來回收垃圾,主線程結束,守護線程一起結束。

    什么是非守護線程?
    與main函數互不影響。
    自己創建線程叫做用戶線程,如果主線程停止了,不會影響用戶線程,用戶線程也叫非守護線程。

    非守護線程演示代碼:

    public static void main(String[] args) {new Thread(new Runnable() {@lombok.SneakyThrowspublic void run() {for (int i = 0; i <= 30; i++) {Thread.sleep(300);System.out.println(i);}}}, "線程名").start();System.out.println("主線程執行完畢");}

    執行結果:
    主線程結束和非守護線程沒有依賴關系。

    設置守護線程

    thread.setDaemon(true);

    讓守護線程和主線程一起銷毀。

    public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@SneakyThrowspublic void run() {for (int i = 1000; i <= 3000; i++) {System.out.println(i);}}}, "線程名");thread.setDaemon(true);thread.start();for (int i = 0; i <500; i++){System.out.println(i);}System.out.println("主線程執行完畢");}

    多線程運行狀態

  • 新建狀態
    new Thread

  • 就緒狀態
    就緒狀態,等待cpu調度

  • 運行狀態
    獲取cpu調度權

  • 死亡狀態
    run方法執行完畢,或者stop方法

  • 休眠(阻塞)狀態
    調用了sleep方法或者wait()方法,運行狀態轉到阻塞狀態,再到就緒狀態

  • join()方法作用

    現有線程A和線程B,線程A調用了線程B的join方法,A等待B線程執行完畢之后再繼續執行。也就是說線程A在調用B的join方法后,釋放了執行權,讓B先執行。

    主線程讓子線程先執行,方法:在主函數中調用子線程的join方法,例子如下:

    @SneakyThrowspublic static void main(String[] args) {Thread thread1 = new Thread(new Runnable() {@SneakyThrowspublic void run() {for (int i = 1000; i <= 1500; i++) {System.out.println(i);}System.out.println("子線程執行完畢!");}});thread1.start();thread1.join();for (int i = 0; i <= 50; i++) {System.out.println(i);}}

    面試題順序執行T1,T2,T3

    現有T1,T2,T3三個線程,怎么保證T2在T1執行完后執行,T3在T2執行完后執行?

    @SneakyThrowspublic static void main(String[] args) {final Thread thread1 = new Thread(new Runnable() {public void run() {for (int i = 0; i <= 10; i++) {System.out.println(i);}System.out.println("子線程1執行完畢!");}});final Thread thread2 = new Thread(new Runnable() {@SneakyThrowspublic void run() {thread1.join();for (int i = 11; i <= 20; i++) {System.out.println(i);}System.out.println("子線程2執行完畢!");}});Thread thread3 = new Thread(new Runnable() {@SneakyThrowspublic void run() {thread2.join();for (int i = 21; i <= 30; i++) {System.out.println(i);}System.out.println("子線程3執行完畢!");}});thread1.start();thread2.start();thread3.start();}

    案例多線程分批處理數據

    端口掃描

    public void threadScanPort() {ExecutorService executorService = Executors.newFixedThreadPool(100);portCount.set(0);int totalThreadNum = 100;for (int n = 0; n <= totalThreadNum; n++) {executorService.execute(new ScanHandler(n, totalThreadNum));}} class ScanHandler implements Runnable {//用于端口掃描的總共線程數private int totalThreadNum;// 線程號private int threadNo;public ScanHandler(int threadNo, int totalThreadNum) {this.totalThreadNum = totalThreadNum;this.threadNo = threadNo;}@Overridepublic void run() {int startPort = Integer.parseInt(startPortField.getText());int endPort = Integer.parseInt(endPortField.getText());String host = targetIp.getText();//startPort和endPort為成員變量,表示需要掃描的起止端口for (int port = startPort + threadNo; port <= endPort; port = port + totalThreadNum) {try {Socket socket = new Socket();socket.connect(new InetSocketAddress(host, port), 200);socket.close();String msg = "端口 " + port + " is open\n";Platform.runLater(() -> {taDisplay.appendText(msg);});} catch (IOException e) {System.out.println(port + "is close");}portCount.incrementAndGet();//掃描的端口數+1}if (portCount.get() == (endPort - startPort + 1)) {portCount.incrementAndGet();//加1,使得不再輸出下面的線程掃描結束的信息Platform.runLater(() -> {taDisplay.appendText("\n----------------多線程掃描結束--------------------\n");});}}}

    總結

    以上是生活随笔為你收集整理的闭关修炼(一)多线程的全部內容,希望文章能夠幫你解決所遇到的問題。

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