欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中創(chuàng)建線程的四種方法解析

 更新時(shí)間:2023年10月21日 10:03:29   作者:浪浪山的猿  
這篇文章主要介紹了Java中創(chuàng)建線程的四種方法解析,線程是Java編程語言中的一個(gè)重要概念,它允許程序在同一時(shí)間執(zhí)行多個(gè)任務(wù),線程是程序中的執(zhí)行路徑,可以同時(shí)執(zhí)行多個(gè)線程,每個(gè)線程都有自己的執(zhí)行流程,需要的朋友可以參考下

前言

在 Java 中,實(shí)現(xiàn)多線程的主要有以下四種

  1. 繼承 Thread 類,重寫 run() 方法;
  2. 實(shí)現(xiàn) Runnable 接口,實(shí)現(xiàn) run() 方法,并將 Runnable 實(shí)現(xiàn)類的實(shí)例作為 Thread 構(gòu)造函數(shù)的參數(shù) target;
  3. 實(shí)現(xiàn) Callable 接口,實(shí)現(xiàn) call() 方法,然后通過 FutureTask 包裝器來創(chuàng)建 Thread 線程;
  4. 通過 ThreadPoolExecutor 創(chuàng)建線程池,并從線程池中獲取線程用于執(zhí)行任務(wù);

繼承Thread類

創(chuàng)建步驟:

  1. 定義類繼承Thread;
  2. 重寫Thread類中的run方法;
  3. 實(shí)例化線程對象;
  4. 調(diào)用線程的start方法開啟線程;

代碼:

package com.scg.springcloudordercenter.controller;
 
// 1.繼承Thread類
public class ThreadDemo extends Thread{
 
    private int ticket=20;
 
    // 2.重寫run 方法
    public void run(){
        for(int i=0;i<20;i++){
 
            if(this.ticket>0){
                System.out.println("剩余票數(shù)=="+ticket--);
            }
        }
 
    }
}
 
class ThreadTest {
    public static void main(String[] args) {
        // 3.實(shí)例化線程對象
        ThreadDemo md = new ThreadDemo() ;
        // 4.調(diào)用start()開啟線程
        md.start();
    }
}
 
 

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

創(chuàng)建步驟:

  1. 實(shí)現(xiàn)Runnable接口;
  2. 重寫Run()方法;
  3. 實(shí)例化實(shí)現(xiàn)類;
  4. 將實(shí)例化線程類轉(zhuǎn)化為線程對象;
  5. 開啟線程 調(diào)用start()方法;

代碼

package com.scg.springcloudordercenter.controller;
 
 
// 1.實(shí)現(xiàn)Runnable類
public class RunnableDemo implements Runnable{
 
    private int ticket=20;
 
    // 2.重寫run 方法
    public void run(){
        for(int i=0;i<20;i++){
 
            if(this.ticket>0){
                System.out.println("剩余票數(shù)=="+ticket--);
            }
        }
 
    }
}
 
class RunnableTest {
    public static void main(String[] args) {
        // 3.實(shí)例化實(shí)現(xiàn)類
        RunnableDemo rd = new RunnableDemo() ;
        // 4.將實(shí)例化實(shí)現(xiàn)類轉(zhuǎn)化為線程對象
        Thread thread = new Thread(rd);
        // 5.開啟線程
        thread.start();
    }
}
 
 
實(shí)現(xiàn) Runnable 接口比繼承 Thread 類所具有的優(yōu)勢主要有:
① 可以避免 JAVA 中單繼承的限制;
② 線程池只能放入實(shí)現(xiàn) Runable 或 Callable類線程,不能直接放入繼承 Thread 的類
③ 代碼可以被多個(gè)線程共享,代碼和數(shù)據(jù)獨(dú)立,適合多個(gè)相同的程序代碼的線程去處理同一個(gè)資源的情況

實(shí)現(xiàn)Callable接口

實(shí)現(xiàn)步驟

1、定義一個(gè)線程任務(wù)類實(shí)現(xiàn)Callable接口,聲明線程執(zhí)行的結(jié)果類型。

2、重寫線程任務(wù)類的call()方法,這個(gè)方法可以直接返回執(zhí)行的結(jié)果。

3、創(chuàng)建一個(gè)Callable的線程任務(wù)對象。

4、把Callable的線程任務(wù)對象包裝成一個(gè)未來任務(wù)對象。

5、把未來任務(wù)對象包裝成線程對象。

6、調(diào)用線程start()方法,啟動(dòng)線程。

7、獲取線程執(zhí)行結(jié)果。

代碼:

/**
 * @author gf
 * @date 2023/2/22
 */
// 1、定義一個(gè)線程任務(wù)類實(shí)現(xiàn)Callable接口,聲明線程執(zhí)行的結(jié)果類型。
public class CallableTicket implements Callable<Object > {
 
    private int ticket=20;
 
    // 2、重寫線程任務(wù)類的call()方法,這個(gè)方法可以直接返回執(zhí)行的結(jié)果。
    @Override
    public Object  call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                sum += i;
            }
        }
        return sum;
    }
 
}
package com.scg.springcloudordercenter.controller;
 
import java.util.concurrent.FutureTask;
 
/**
 * @author gf
 * @date 2023/2/22
 */
public class CallableMain {
 
    public static void main(String[] args) {
 
        // 3、創(chuàng)建一個(gè)Callable的線程任務(wù)對象。
        CallableTicket callableTicket = new CallableTicket();
 
        // 4、把Callable的線程任務(wù)對象包裝成一個(gè)未來任務(wù)對象。
        FutureTask futureTask = new FutureTask(callableTicket);
 
        // 5、把未來任務(wù)對象包裝成線程對象。
        Thread thread = new Thread(futureTask);
 
        // 6、調(diào)用線程start()方法,啟動(dòng)線程。
        thread.start();
 
        // 7、獲取線程執(zhí)行結(jié)果。如果此時(shí)獲取結(jié)果的任務(wù)還未執(zhí)行完成,會(huì)讓出CPU,直至任務(wù)執(zhí)行完成才獲取結(jié)果。
        try {
            //6.獲取Callable中call方法的返回值
            //get()返回值即為FutureTask構(gòu)造器參數(shù)Callable實(shí)現(xiàn)類重寫的call()方法返回值。
            Object sum = futureTask.get();
            System.out.println("總和為:"+sum);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
 
    }
}

優(yōu)點(diǎn):

與使用Runnable相比,Callable功能更強(qiáng)大

  • 相比run方法,可以有返回值。
  • 方法可以拋異常。
  • 支持泛型的返回值。
  • 需要借助FutureTask類,比如獲取返回結(jié)果。

Future接口

  • 可以對具體Runnable、Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢是否完成、獲取結(jié)果等。
  • FutureTask是Future接口的唯一實(shí)現(xiàn)類。
  • FutureTask同時(shí)實(shí)現(xiàn)了Runable,F(xiàn)uture接口。它既可以作為Runnable被線程執(zhí)行,又可以作為Future得到Callable的返回值

使用線程池

通過Executors創(chuàng)建

它提供了四種線程池:

  1. newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
  2. newFixedThreadPool 創(chuàng)建一個(gè)定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待。
  3. newScheduledThreadPool 創(chuàng)建一個(gè)定長線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
  4. newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。
public class Demo01 {
    public static void main(String[] args) {
        //ExecutorService threadPool = Executors.newSingleThreadExecutor(); //創(chuàng)建單個(gè)線程
        //ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);//創(chuàng)建一個(gè)固定大小的線程池
        //ExecutorService threadPool = Executors.newFixedThreadPool(5); //創(chuàng)建一個(gè)固定大小的線程池
        ExecutorService threadPool = Executors.newCachedThreadPool(); //創(chuàng)建大小可伸縮的線程池
 
        try {
            for (int i = 0; i < 30; i++) {
                //使用線程池來創(chuàng)建線程
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown(); //線程池使用完畢后需要關(guān)閉
        }
 
    }
}

注意:不建議使用這種方法創(chuàng)建線程池。因?yàn)閚ewFixedThreadPool 和newSingleThreadExecutor允許的最大請求隊(duì)列長度為Integer.MAX_VALUE,可能會(huì)堆積大量的請求,從而導(dǎo)致OOM。newCachedThreadPoo和newScheduledThreadPool允許的創(chuàng)建線程的最大數(shù)量為Integer.MAX_VALUE,,從而導(dǎo)致OOM。

通過ThreadPoolExecutor創(chuàng)建

ThreadPoolExecutor有7個(gè)核心參數(shù)

  1. ThreadPoolExecutor(int corePoolSize, //核心線程池大小,始終存在
  2. int maximumPoolSize, //最大線程數(shù)
  3. long keepAliveTime, //空閑線程等待時(shí)間,超時(shí)則銷毀
  4. TimeUnit unit, //時(shí)間單位
  5. BlockingQueue<Runnable> workQueue, //等待阻塞隊(duì)列
  6. ThreadFactory threadFactory, //線程工廠
  7. RejectedExecutionHandler handler) //線程拒絕策略

其最后一個(gè)參數(shù)拒絕策略共有四種:

  • new ThreadPoolExecutor.AbortPolicy():達(dá)到最大承載量,不再處理,并且拋出異常
  • new ThreadPoolExecutor.CallerRunsPolicy():達(dá)到最大承載量,從哪來的去哪里
  • new ThreadPoolExecutor.DiscardPolicy():達(dá)到最大承載量,丟掉任務(wù),但不拋出異常
  • new ThreadPoolExecutor.DiscardOldestPolicy():達(dá)到最大承載量,嘗試與最早執(zhí)行的線程去競爭,不拋出異常
public class Demo02 {
    public static void main(String[] args) {
        //new ThreadPoolExecutor.AbortPolicy():達(dá)到最大承載量,不再處理,并且拋出異常
        //new ThreadPoolExecutor.CallerRunsPolicy():達(dá)到最大承載量,從哪來的去哪里
        //new ThreadPoolExecutor.DiscardPolicy():達(dá)到最大承載量,丟掉任務(wù),但不拋出異常
        //new ThreadPoolExecutor.DiscardOldestPolicy():達(dá)到最大承載量,嘗試與最早執(zhí)行的線程去競爭,不拋出異常
 
        //最大線程池大小該如何定義
        //1.cpu密集型,邏輯處理器個(gè)數(shù)
        //2.io密集型 > 判斷程序十分耗IO的線程,最大線程池大小應(yīng)該比這個(gè)大
        int maxPools= Runtime.getRuntime().availableProcessors();
        System.out.println(maxPools);
 
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,
                maxPools,
                3,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );
 
        try {
            for (int i = 0; i < 10; i++) {
                //使用線程池來創(chuàng)建線程
                //最大承載:maximumPoolSize+workQueue,超過執(zhí)行拒絕策略
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+" ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown(); //線程池使用完畢后需要關(guān)閉
        }
 
    }
}

使用線程池的優(yōu)點(diǎn);

1.減少資源的消耗。重復(fù)利用已經(jīng)創(chuàng)建的線程,避免頻繁的創(chuàng)造和銷毀線程,減少消耗。

2.提高響應(yīng)速度。當(dāng)執(zhí)行任務(wù)時(shí),不需要去創(chuàng)建線程再來執(zhí)行,只要調(diào)動(dòng)現(xiàn)有的線程來執(zhí)行即可。

3.提高了線程的管理性。線程是稀缺資源,使用線程池可以進(jìn)行統(tǒng)一的分配、調(diào)優(yōu)和監(jiān)控。

到此這篇關(guān)于Java中創(chuàng)建線程的四種方法解析的文章就介紹到這了,更多相關(guān)Java創(chuàng)建線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven+oracle+SSM搭建簡單項(xiàng)目的方法

    Maven+oracle+SSM搭建簡單項(xiàng)目的方法

    本篇文章主要介紹了Maven+oracle+SSM搭建簡單項(xiàng)目的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(51)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(51)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-08-08
  • 一文詳解Spring?security框架的使用

    一文詳解Spring?security框架的使用

    Spring?Security是一個(gè)基于Spring框架的安全認(rèn)證和授權(quán)框架,它提供了一套全面的安全解決方案,可以在Web應(yīng)用、移動(dòng)應(yīng)用和Web服務(wù)等不同場景下使用。本文就來詳細(xì)聊聊它的使用吧
    2023-03-03
  • 一文教你掌握J(rèn)ava如何實(shí)現(xiàn)判空

    一文教你掌握J(rèn)ava如何實(shí)現(xiàn)判空

    實(shí)際項(xiàng)目中我們會(huì)有很多地方需要判空校驗(yàn),如果不做判空校驗(yàn)則可能產(chǎn)生NullPointerException異常。所以本文小編為大家整理了Java中幾個(gè)常見的判空方法,希望對大家有所幫助
    2023-04-04
  • Java利用httpclient通過get、post方式調(diào)用https接口的方法

    Java利用httpclient通過get、post方式調(diào)用https接口的方法

    這篇文章主要介紹了Java利用httpclient通過get、post方式調(diào)用https接口的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Kafka是什么及如何使用SpringBoot對接Kafka(最新推薦)

    Kafka是什么及如何使用SpringBoot對接Kafka(最新推薦)

    這篇文章主要介紹了Kafka是什么,以及如何使用SpringBoot對接Kafka,今天我們通過一個(gè)Demo講解了在SpringBoot中如何對接Kafka,也介紹了下關(guān)鍵類?KafkaTemplate,需要的朋友可以參考下
    2023-11-11
  • MyBatis還是JPA?終于有答案了

    MyBatis還是JPA?終于有答案了

    這篇文章主要介紹了MyBatis還是JPA,中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 使用maven項(xiàng)目pom.xml文件配置打包功能和靜態(tài)資源文件自帶版本號功能

    使用maven項(xiàng)目pom.xml文件配置打包功能和靜態(tài)資源文件自帶版本號功能

    在Maven項(xiàng)目中,通過pom.xml文件配置打包功能,可以控制構(gòu)建過程,生成可部署的包,同時(shí),為了緩存控制與版本更新,可以在打包時(shí)給靜態(tài)資源文件如JS、CSS添加版本號,這通常通過插件如maven-resources-plugin實(shí)現(xiàn)
    2024-09-09
  • Java中List對象集合按對象中某字段進(jìn)行排序舉例

    Java中List對象集合按對象中某字段進(jìn)行排序舉例

    這篇文章主要給大家介紹了關(guān)于Java中List對象集合按對象中某字段進(jìn)行排序的相關(guān)資料,我們在日常開發(fā)中也經(jīng)常會(huì)用到排序算法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java Lambda 表達(dá)式詳解及示例代碼

    Java Lambda 表達(dá)式詳解及示例代碼

    本文主要介紹Java Lambda 表達(dá)式的知識,這里整理了相關(guān)資料,JavaLambda 是Java8 引入的新功能,有興趣的小伙伴可以參考下
    2016-09-09

最新評論