最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

對(duì)Spring中bean線程安全的討論

 更新時(shí)間:2025年06月29日 13:51:21   作者:找不到、了  
這篇文章主要介紹了對(duì)Spring中bean線程安全的討論,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring容器中的Bean是否線程安全,容器本身并沒(méi)有提供Bean的線程安全策略,因此Spring容器中的Bean本身不具備線程安全的特性,但是具體要結(jié)合具體的scope、靜態(tài)變量、常量、成員變量等多種屬性去研究。   

1、Bean狀態(tài)介紹

1.1、有狀態(tài)對(duì)象

有實(shí)例變量的對(duì)象,即每個(gè)用戶最初都會(huì)得到一個(gè)初始的bean,可以保存數(shù)據(jù),是非線程安全的。

每個(gè)用戶有自己特有的一個(gè)實(shí)例,在用戶的生存期內(nèi),bean保持了用戶的信息,即“有狀態(tài)”;一旦用戶滅亡(調(diào)用結(jié)束或?qū)嵗Y(jié)束),bean的生命期也告結(jié)束。

代碼示例:

@Service
public class Counter {
    private int count = 0;  // 有狀態(tài):保存實(shí)例變量

    public void increment() {
        count++;  // 非原子操作,線程不安全
    }

    public int getCount() {
        return count;
    }
}
  • 多個(gè)線程調(diào)用 increment() 時(shí),count++操作可能因指令重排或并發(fā)寫(xiě)入導(dǎo)致數(shù)據(jù)不一致。

1.2、無(wú)狀態(tài)對(duì)象

沒(méi)有實(shí)例變量的對(duì)象,不能保存數(shù)據(jù),是不變類,是線程安全的。

  • bean一旦實(shí)例化就被加進(jìn)會(huì)話池中,各個(gè)用戶都可以共用。即使用戶已經(jīng)消亡,bean 的生命期也不一定結(jié)束,它可能依然存在于會(huì)話池中,供其他用戶調(diào)用。
  • 由于沒(méi)有特定的用戶,那么也就不能保持某一用戶的狀態(tài),所以叫無(wú)狀態(tài)bean。但無(wú)狀態(tài)會(huì)話bean 并非沒(méi)有狀態(tài),
  • 如果有自己的屬性(變量),那么這些變量就會(huì)受到所有調(diào)用它的用戶的影響。

代碼示例如下:

@Service
public class Calculator {
    // 無(wú)狀態(tài):不保存任何實(shí)例變量
    public int add(int a, int b) {
        return a + b;
    }
}
  • 多個(gè)線程調(diào)用add(1,2)時(shí),結(jié)果不會(huì)互相影響。

兩者的區(qū)別和聯(lián)系:

2、Bean作用域

bean的生命周期如下所示:

實(shí)例化--->設(shè)置屬性--->初始化--->銷毀

Spring 的 bean 作用域(scope)類型:

1、singleton:單例,默認(rèn)作用域。

  • 優(yōu)點(diǎn): 節(jié)省內(nèi)存,因?yàn)橹淮嬖谝粋€(gè)實(shí)例。
  • 缺點(diǎn): 由于多個(gè)線程可能共享同一個(gè)實(shí)例,需要格外注意線程安全(非線程安全的狀態(tài)字段可能導(dǎo)致問(wèn)題)

2、prototype:原型,每次創(chuàng)建一個(gè)新對(duì)象。

3、request:請(qǐng)求,每次Http請(qǐng)求創(chuàng)建一個(gè)新對(duì)象,適用于WebApplicationContext環(huán)境下。

4、session:會(huì)話,同一個(gè)會(huì)話共享一個(gè)實(shí)例,不同會(huì)話使用不用的實(shí)例。

5、global-session:全局會(huì)話,所有會(huì)話共享一個(gè)實(shí)例。

3、線程安全:

從單例與原型Bean分別進(jìn)行說(shuō)明。

3.1、bean的分類

1、原型Bean

對(duì)于原型Bean,每次創(chuàng)建一個(gè)新對(duì)象,也就是線程之間并不存在Bean共享,自然是不會(huì)有線程安全的問(wèn)題。

2、單例Bean

對(duì)于單例Bean,所有線程都共享一個(gè)單例實(shí)例Bean,因此是存在資源的競(jìng)爭(zhēng)。

3.2、bean的安全

1、@Controller相關(guān)

可以這樣理解:

如果單例Bean,是一個(gè)無(wú)狀態(tài)Bean,在線程中的操作不會(huì)對(duì)Bean的成員執(zhí)行查詢以外的操作,那么這個(gè)單例Bean是線程安全的。

比如Spring mvc 的 Controller、Service、Dao等,這些Bean大多是無(wú)狀態(tài)的,默認(rèn)情況下@Controller沒(méi)有加上@Scope,默認(rèn)Scope就是默認(rèn)值singleton,單例的 ,系統(tǒng)只會(huì)初始化一次 Controller 容器,只關(guān)注于方法本身。

但是,如果每次請(qǐng)求的都是同一個(gè) Controller 容器里面的非線程安全的字段,那么就不是線程安全的。

代碼示例:

@RestController
public class TestController {
    //非線程安全的字段
    private int var = 0;
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var));
        return "普通變量var:" + var ;
    }
}

輸出:
普通變量var:1
普通變量var:2
普通變量var:3

修改了作用于改為:prototype

每個(gè)請(qǐng)求都單獨(dú)創(chuàng)建一個(gè) Controller 容器,所以各個(gè)請(qǐng)求之間是線程安全的。

@RestController
@Scope(value = "prototype") // 加上@Scope注解,有2個(gè)取值:?jiǎn)卫?singleton 多實(shí)例-prototype
public class TestController {
    private int var = 0;
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var));
        return "普通變量var:" + var ;
    }
}
輸出:
普通變量var:1
普通變量var:1
普通變量var:1

總結(jié)

1、@Controller/@Service 等容器中,默認(rèn)情況下,scope值是單例- singleton 的,是線程不安全的。

2、盡量不要在 @Controller/@Service 等容器中定義靜態(tài)變量,不論是單例( singleton )還是多實(shí)例( prototype )都是線程不安全的。

3、默認(rèn)注入的Bean對(duì)象,在不設(shè)置scope的時(shí)候也是線程不安全的。

4、一定要定義變量的話,用 ThreadLocal 來(lái)封裝,這個(gè)是線程安全的。

2、@prototype注解

@Scope 注解的 prototype 實(shí)例一定就是線程安全的嗎?

答案是否定的。上面已經(jīng)解釋過(guò)了,需要根據(jù)多方位去考量。

@RestController
@Scope(value = "prototype") // 加上@Scope注解,有2個(gè)取值:?jiǎn)卫?singleton 多實(shí)例-prototype
public class TestController {
    private int var = 0;
    //只會(huì)初始化一次,因此也非線程安全的變量
    private static int staticVar = 0;
?
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var)+ "---靜態(tài)變量staticVar:" + (++staticVar));
        return "普通變量var:" + var + "靜態(tài)變量staticVar:" + staticVar;
    }
}

輸出:
普通變量var:1---靜態(tài)變量staticVar:1
普通變量var:1---靜態(tài)變量staticVar:2
普通變量var:1---靜態(tài)變量staticVar:3

總結(jié):線程安全在于怎樣去定義變量以及 Controller 的配置。

示例:

config里面自己定義的Bean: User

@Configuration
public class MyConfig {
    @Bean
    public User user(){
        return new User();
    }
}
@RestController
@Scope(value = "singleton") // prototype singleton
public class TestController {
?
    private int var = 0; // 定義一個(gè)普通變量
?
    private static int staticVar = 0; // 定義一個(gè)靜態(tài)變量
?
    @Value("${test-int}")
    private int testInt; // 從配置文件中讀取變量
?
    ThreadLocal<Integer> tl = new ThreadLocal<>(); // 用ThreadLocal來(lái)封裝變量
?
    @Autowired
    private User user; // 注入一個(gè)對(duì)象來(lái)封裝變量
?
    @GetMapping(value = "/test_var")
    public String test() {
        tl.set(1);
        System.out.println("先取一下user對(duì)象中的值:"+user.getAge()+"===再取一下hashCode:"+user.hashCode());
        user.setAge(1);
        System.out.println("普通變量var:" + (++var) + "===靜態(tài)變量staticVar:" + (++staticVar) + "===配置變量testInt:" + (++testInt)
                + "===ThreadLocal變量tl:" + tl.get()+"===注入變量user:" + user.getAge());
        return "普通變量var:" + var + ",靜態(tài)變量staticVar:" + staticVar + ",配置讀取變量testInt:" + testInt + ",ThreadLocal變量tl:"
                + tl.get() + "注入變量user:" + user.getAge();
    }
}

輸出:

先取一下user對(duì)象中的值:0===再取一下hashCode:241165852

普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

先取一下user對(duì)象中的值:1===再取一下hashCode:241165852

普通變量var:2===靜態(tài)變量staticVar:2===配置變量testInt:2===ThreadLocal變量tl:1===注入變量user:1

先取一下user對(duì)象中的值:1===再取一下hashCode:241165852

普通變量var:3===靜態(tài)變量staticVar:3===配置變量testInt:3===ThreadLocal變量tl:1===注入變量user:1

在單例模式下 Controller 中只有用 ThreadLocal 封裝的變量是線程安全的。可以看到3次請(qǐng)求結(jié)果里面只有 ThreadLocal 變量值每次都是從 0+1=1 的,其他的幾個(gè)都是累加的,而 user 對(duì)象呢,默認(rèn)值是0,第二交取值的時(shí)候就已經(jīng)是1了,關(guān)鍵它的 hashCode 是一樣的,說(shuō)明每次請(qǐng)求調(diào)用的都是同一個(gè) user 對(duì)象。

TestController 上的 @Scope 注解的屬性改一下改成多實(shí)例的: @Scope(value = "prototype") ,其他都不變,再次請(qǐng)求,結(jié)果如下:

public class MyConfig {
    @Bean
    @Scope(value = "prototype")
    public User user(){
        return new User();
    }    
}
@RestController
@Scope(value = "prototype") // prototype singleton
public class TestController {
?
    private int var = 0; // 定義一個(gè)普通變量
?
    private static int staticVar = 0; // 定義一個(gè)靜態(tài)變量
?
    @Value("${test-int}")
    private int testInt; // 從配置文件中讀取變量
?
    ThreadLocal<Integer> tl = new ThreadLocal<>(); // 用ThreadLocal來(lái)封裝變量
?
    @Autowired
    private User user; // 注入一個(gè)對(duì)象來(lái)封裝變量
?
    @GetMapping(value = "/test_var")
    public String test() {
        tl.set(1);
        System.out.println("先取一下user對(duì)象中的值:"+user.getAge()+"===再取一下hashCode:"+user.hashCode());
        user.setAge(1);
        System.out.println("普通變量var:" + (++var) + "===靜態(tài)變量staticVar:" + (++staticVar) + "===配置變量testInt:" + (++testInt)
                + "===ThreadLocal變量tl:" + tl.get()+"===注入變量user:" + user.getAge());
        return "普通變量var:" + var + ",靜態(tài)變量staticVar:" + staticVar + ",配置讀取變量testInt:" + testInt + ",ThreadLocal變量tl:"
                + tl.get() + "注入變量user:" + user.getAge();
    }
}

先取一下user對(duì)象中的值:0===再取一下hashCode:1612967699
普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

先取一下user對(duì)象中的值:0===再取一下hashCode:985418837
普通變量var:1===靜態(tài)變量staticVar:2===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

先取一下user對(duì)象中的值:0===再取一下hashCode:1958952789
普通變量var:1===靜態(tài)變量staticVar:3===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

3、靜態(tài)變量

靜態(tài)變量的生命周期由 JVM 管理,與 Spring 無(wú)關(guān)。所有實(shí)例(單例或原型)共享同一個(gè)靜態(tài)變量。

@Component
public class MyService {
    private static int count = 0; // 靜態(tài)變量

    public void increment() {
        count++; // 多線程環(huán)境下可能出問(wèn)題
    }
}

在 Spring 中,無(wú)論是單例(Singleton)作用域還是原型(Prototype)作用域的 Bean,只要在類中定義了靜態(tài)變量(static 變量),都可能存在線程安全問(wèn)題。

總結(jié):多實(shí)例模式下普通變量,取配置的變量還有 ThreadLocal 變量都是線程安全的,而靜態(tài)變量和 user 對(duì)象中的變量都是非線程安全的。

4、ThreadLocal

4.1、概念

ThreadLocal 類提供了線程局部變量,每個(gè)線程可以將一個(gè)值存在 ThreadLocal 對(duì)象中,其他線程無(wú)法訪問(wèn)這些值。每個(gè)線程都有自己獨(dú)立的變量副本。

ThreadLocal 的初始值可通過(guò) withInitial() 方法設(shè)置:

private static final ThreadLocal<String> requestId = 
    ThreadLocal.withInitial(() -> "default-id");

簡(jiǎn)單的內(nèi)存模型:

+-----------------+          +------------------+
|    Thread A     |          |    Thread B      |
+-----------------+          +------------------+
| ThreadLocal     |          | ThreadLocal      |
| - value: 123    |          | - value: 456     |
+-----------------+          +------------------+

Thread A and Thread B can have different values in the same ThreadLocal.

不同線程直接保存了不同的值。

4.2、優(yōu)點(diǎn)

若單例 Bean 需要保存線程私有的狀態(tài)(如用戶請(qǐng)求上下文),多線程場(chǎng)景下,多個(gè)線程對(duì)這個(gè)單例Bean的成員變量并不存在資源的競(jìng)爭(zhēng),因?yàn)門hreadLocal為每個(gè)線程保存線程私有的數(shù)據(jù)。這是一種以空間換時(shí)間的方式。

4.3、原理

如下圖所示:

調(diào)用 ThreadLocal.set(value)方法時(shí),它會(huì)將這個(gè)值與當(dāng)前線程關(guān)聯(lián),而該值被存儲(chǔ)在當(dāng)前線程的一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)中。通過(guò) ThreadLocal.get()方法,可以獲取當(dāng)前線程所關(guān)聯(lián)的值。

  • 核心機(jī)制:每個(gè)線程內(nèi)部維護(hù)一個(gè) ThreadLocalMap(類似鍵值對(duì)存儲(chǔ),以 ThreadLocal 對(duì)象為鍵,存儲(chǔ)線程私有的變量。
  • 數(shù)據(jù)隔離:線程通過(guò)自己的 ThreadLocalMap 訪問(wèn)變量,不同線程之間的數(shù)據(jù)互不影響。
  • 內(nèi)存模型
Thread-1 → ThreadLocalMap → { ThreadLocalA → Value1, ThreadLocalB → Value2 }
Thread-2 → ThreadLocalMap → { ThreadLocalA → Value3, ThreadLocalB → Value4 }

4.4、注意

由于ThreadLocal里面維護(hù)了ThreadLocalMap類,如下圖所示:

而TheadLocalMap是由Entry[]組成組成,Entry[]維護(hù)了多個(gè)entry。如下所示:

一個(gè)entry由key(threadlocal)和value,Entry繼承了弱引用,關(guān)于弱引用可參考:對(duì)Java 資源管理和引用體系的介紹

如下圖所示:entry

如果使用不當(dāng),會(huì)引發(fā)oom問(wèn)題,主要是由GC回收機(jī)制和內(nèi)存結(jié)構(gòu)兩者引起。

可參考:就ThreadLocal使用時(shí)OOM的討論

4.5、使用場(chǎng)景

  • 用戶會(huì)話信息: 在 web 應(yīng)用中維護(hù)用戶的會(huì)話信息,避免將狀態(tài)信息寫(xiě)到全局上下文。
  • 數(shù)據(jù)庫(kù)連接: 在線程中維護(hù)數(shù)據(jù)源連接,避免不同線程之間共享資源引起的競(jìng)爭(zhēng)。
  • 事務(wù)管理(如 Spring 的 TransactionSynchronizationManager)。

以下是一個(gè)簡(jiǎn)單的 Spring Bean 示例,展示如何在 Spring 中使用 ThreadLocal 來(lái)存儲(chǔ)用戶會(huì)話信息。

1.定義一個(gè) ThreadLocal Storage

import org.springframework.stereotype.Component;

@Component
public class UserContext {
    private static final ThreadLocal<String> userHolder = new ThreadLocal<>();

    public void setCurrentUser(String username) {
        userHolder.set(username);
    }

    public String getCurrentUser() {
        return userHolder.get();
    }

    //清理 ThreadLocal,防止內(nèi)存泄漏
    public void clear() {
        userHolder.remove(); // 清除當(dāng)前線程中的值
    }
}

2.使用 UserContext

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserContext userContext;

    public void login(String username) {
        userContext.setCurrentUser(username);
        System.out.println("User logged in: " + userContext.getCurrentUser());
    }

    public void logout() {
        System.out.println("User logged out: " + userContext.getCurrentUser());
        userContext.clear();
    }
}

3 示例測(cè)試類

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testThreadLocal() {
        userService.login("Alice");
        userService.logout();

        // Clear (will just have no output, but it demonstrates functionality)
        userService.login("Bob");
        userService.logout();
    }
}

4. 圖形展示

在多線程環(huán)境中的 ThreadLocal 可能如下圖所示:

+-------------------+
|      UserContext  |
|-------------------|
| ThreadLocal       |
| - userHolder      |
+-------------------+
     |         |
     |         |
     v         v
+------------+ +-------------+
| Thread A   | | Thread B    |
|------------| |------------ |
| - user: "Alice" | - user: "Bob" |
+------------+ +--------------+

在每個(gè)線程中,UserContext 提供了對(duì) ThreadLocal 變量獨(dú)立的值,使得 Thread A 可以存儲(chǔ)與 Thread B 不同的用戶會(huì)話信息。

5、解決方案

根據(jù)以上介紹Spring Bean的線程安全問(wèn)題,以下是各種常用的解決方案。

1、同步機(jī)制去處理

synchronized 關(guān)鍵字或者 ReentrantLock 可重入鎖。

示例:

synchronized介紹:

 import org.springframework.stereotype.Component;
 ?
 @Component
 public class OrderServiceBean {
 ?
     private int orderStatus;
 ?
     public synchronized void updateOrderStatus() {
         // 這里進(jìn)行更新訂單狀態(tài)的具體業(yè)務(wù)邏輯,比如根據(jù)某些條件修改orderStatus的值
         orderStatus++;
     }
 ?
     public int getOrderStatus() {
         return orderStatus;
     }
 }

ReentrantLock介紹:

 import org.springframework.stereotype.Component;
 import java.util.concurrent.locks.ReentrantLock;
 ?
 @Component
 public class OrderServiceBean {
 ?
     private int orderStatus;
     private ReentrantLock lock = new ReentrantLock();
 ?
     public void updateOrderStatus() {
         lock.lock();
         try {
             // 這里進(jìn)行更新訂單狀態(tài)的具體業(yè)務(wù)邏輯,比如根據(jù)某些條件修改orderStatus的值
             orderStatus++;
         } finally {
             lock.unlock();
         }
     }
 ?
     public int getOrderStatus() {
         return orderStatus;
     }
 }

2、Treadlocal對(duì)象(推薦)

3、采用不可變對(duì)象(Immutable Objects)

設(shè)置final對(duì)象或者成員變量屬性。

4、使用原子類(Atomic Classes)

 import org.springframework.stereotype.Component;
 import java.util.concurrent.atomic.AtomicInteger;
 ?
 @Component
 public class VisitCountBean {
 ?
     private AtomicInteger visitCount = new AtomicInteger(0);
 ?
     public void incrementVisitCount() {
         visitCount.incrementAndGet();
     }
 ?
     public int getVisitCount() {
         return visitCount.get();
     }
 }

在 Spring 中實(shí)現(xiàn)線程安全,尤其是涉及到多個(gè)線程共享狀態(tài)時(shí),常常需要:

  • 選擇適當(dāng)?shù)?Bean 作用域。
  • 盡量減少或避免可變狀態(tài)。
  • 使用 ThreadLocal 來(lái)管理線程局部數(shù)據(jù)。
  • 使用 AOP 及 Spring 事務(wù)來(lái)處理業(yè)務(wù)邏輯。
  • 實(shí)現(xiàn)良好的設(shè)計(jì)模式以確保代碼的可維護(hù)性。

通過(guò)以上最佳實(shí)踐,可以有效地在 Spring 應(yīng)用中實(shí)現(xiàn)線程安全,確保系統(tǒng)的穩(wěn)定性和數(shù)據(jù)一致性。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 數(shù)組ArrayList常用語(yǔ)法詳解

    Java 數(shù)組ArrayList常用語(yǔ)法詳解

    這篇文章主要介紹了Java 數(shù)組ArrayList常用語(yǔ)法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 一篇文章帶你了解JAVA面對(duì)對(duì)象應(yīng)用

    一篇文章帶你了解JAVA面對(duì)對(duì)象應(yīng)用

    Java是一門面向?qū)ο蟮恼Z(yǔ)言。對(duì)象是Java程序中的基本實(shí)體。除了對(duì)象之外Java程序同樣處理基本數(shù)據(jù)。下面這篇文章主要給大家總結(jié)了關(guān)于Java中面向?qū)ο蟮闹R(shí)點(diǎn),需要的朋友可以參考借鑒,下面來(lái)一起看看吧
    2021-08-08
  • java調(diào)用未知類的指定方法簡(jiǎn)單實(shí)例

    java調(diào)用未知類的指定方法簡(jiǎn)單實(shí)例

    這篇文章介紹了java調(diào)用未知類的指定方法簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下
    2013-09-09
  • Java如何不解壓讀取.zip的文件內(nèi)容

    Java如何不解壓讀取.zip的文件內(nèi)容

    這篇文章主要給大家介紹了關(guān)于Java如何不解壓讀取.zip的文件內(nèi)容的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • JAVA入門教學(xué)之快速搭建基本的springboot(從spring boot到spring cloud)

    JAVA入門教學(xué)之快速搭建基本的springboot(從spring boot到spring cloud)

    本文主要入門者介紹怎么搭建一個(gè)基礎(chǔ)的springboot環(huán)境,本文通過(guò)圖文并茂的形式給大家介紹從spring boot到spring cloud的完美搭建過(guò)程,適用java入門教學(xué),需要的朋友可以參考下
    2021-02-02
  • JAVA項(xiàng)目swing轉(zhuǎn)javafx語(yǔ)法規(guī)則以及示例代碼

    JAVA項(xiàng)目swing轉(zhuǎn)javafx語(yǔ)法規(guī)則以及示例代碼

    這篇文章主要介紹了JAVA項(xiàng)目swing轉(zhuǎn)javafx語(yǔ)法規(guī)則以及示例代碼的相關(guān)資料,文中詳細(xì)講解了主類繼承、窗口創(chuàng)建、布局管理、控件替換、事件監(jiān)聽(tīng)、線程安全、圖標(biāo)設(shè)置、顯示窗口等內(nèi)容,需要的朋友可以參考下
    2025-12-12
  • Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無(wú)向圖的設(shè)計(jì)實(shí)現(xiàn)

    Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無(wú)向圖的設(shè)計(jì)實(shí)現(xiàn)

    加權(quán)無(wú)向圖是一種為每條邊關(guān)聯(lián)一個(gè)權(quán)重值或是成本的圖模型。這種圖能夠自然地表示許多應(yīng)用。這篇文章主要介紹了加權(quán)無(wú)向圖的設(shè)計(jì)與實(shí)現(xiàn),感興趣的可以了解一下
    2022-11-11
  • SpringBoot整合Dozer映射框架流程詳解

    SpringBoot整合Dozer映射框架流程詳解

    dozer是用來(lái)兩個(gè)對(duì)象之間屬性轉(zhuǎn)換的工具,有了這個(gè)工具之后,我們將一個(gè)對(duì)象的所有屬性值轉(zhuǎn)給另一個(gè)對(duì)象時(shí),就不需要再去寫(xiě)重復(fù)的set和get方法了,下面介紹下SpringBoot中Dozer的使用,感興趣的朋友一起看看吧
    2022-07-07
  • Java查看和修改線程優(yōu)先級(jí)操作詳解

    Java查看和修改線程優(yōu)先級(jí)操作詳解

    JAVA中每個(gè)線程都有優(yōu)化級(jí)屬性,默認(rèn)情況下,新建的線程和創(chuàng)建該線程的線程優(yōu)先級(jí)是一樣的。本文將為大家詳解Java查看和修改線程優(yōu)先級(jí)操作的方法,需要的可以參考一下
    2022-08-08
  • Java面向?qū)ο箨P(guān)鍵字extends繼承的深入講解

    Java面向?qū)ο箨P(guān)鍵字extends繼承的深入講解

    繼承就是使用已定義的類作為父類,新建一個(gè)類作為子類使用extends關(guān)鍵字繼承這個(gè)類,這樣就實(shí)現(xiàn)了繼承關(guān)系,這篇文章主要給大家介紹了關(guān)于Java面向?qū)ο箨P(guān)鍵字extends繼承的相關(guān)資料,需要的朋友可以參考下
    2021-08-08

最新評(píng)論

洛南县| 洪洞县| 利辛县| 海兴县| 垣曲县| 万山特区| 吕梁市| 台湾省| 皮山县| 顺昌县| 黎城县| 绿春县| 儋州市| 垣曲县| 嘉鱼县| 寿阳县| 乳山市| 察哈| 修武县| 英德市| 杭锦后旗| 盐亭县| 泊头市| 张家港市| 正宁县| 额尔古纳市| 棋牌| 霍林郭勒市| 宜黄县| 池州市| 汾西县| 井陉县| 上虞市| 林西县| 仁布县| 南溪县| 五莲县| 麦盖提县| 克山县| 阿巴嘎旗| 色达县|