關(guān)于使用ContextClassLoader遇到的問題
關(guān)于使用ContextClassLoader遇到的問題
對ContextClassLoader有一些疑惑:
- 父線程加載的Class,子線程是否可以使用該Class? 答:可以
- 子線程加載的Class,父線程是否可以使用該Class? 答:不可以
- 如果一個(gè)線程加載的Class,其他線程是否可以使用該Class ? 答:不可以
- 怎么使用ContextClassLoader才是正確姿勢呢? 答:取出->更改->還原(finally語句塊)。
關(guān)于上述4點(diǎn)疑問,做了以下測試:
父線程加載的Class,子線程是否可以使用該Class?
/**
* Thread.currentThread().setContextClassLoader
* 如果父線程加載了某個(gè)class, 那么子線程也可以使用該class
*/
public class Test2 {
public static void main(String[] args) throws InterruptedException {
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
MyClassLoader classLoader = new MyClassLoader();
classLoader.setClassFile(new File("D:\\UserService3Impl.class"));
Thread.currentThread().setContextClassLoader(classLoader);
try {
classLoader.loadClass("com.sample.mybatis.service.impl.UserService3Impl");
} catch (Exception e) {
e.printStackTrace();
}
Thread thread = new Thread(() -> {
try {
Class<?> userClass = Thread.currentThread().getContextClassLoader().loadClass("com.sample.mybatis.service.impl.UserService3Impl");
System.out.println(userClass);
UserService3 userObj = (UserService3)userClass.newInstance();
System.out.println(Thread.currentThread().getName() + " ==> " + userObj.getUserNo());
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
}
}運(yùn)行結(jié)果:

結(jié)論:父線程加載的Class,子線程是可以使用該Class
子線程加載的Class,父線程是否可以使用該Class?
/**
* Thread.currentThread().setContextClassLoader
* 如果子線程加載了某個(gè)class, 那么父線程不能共享到該class
*/
public class Test4 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> {
try {
MyClassLoader classLoader = new MyClassLoader();
classLoader.setClassFile(new File("D:\\UserService3Impl.class"));
Thread.currentThread().setContextClassLoader(classLoader);
try {
classLoader.loadClass("com.sample.mybatis.service.impl.UserService3Impl");
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
thread.join();
Class<?> userClass = Thread.currentThread().getContextClassLoader().loadClass("com.sample.mybatis.service.impl.UserService3Impl");
System.out.println(userClass);
UserService3 userObj = (UserService3) userClass.newInstance();
System.out.println(Thread.currentThread().getName() + " ==> " + userObj.getUserNo());
}
}運(yùn)行結(jié)果:

結(jié)論:子線程加載的Class,父線程是不可以使用該Class
如果一個(gè)線程加載的Class,其他線程是否可以使用該Class?
測試代碼:
/**
* 如果兩個(gè)線程不是父子線程, 線程之間不會共享加載過的class
*/
public class Test3 {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
MyClassLoader classLoader = new MyClassLoader();
classLoader.setClassFile(new File("D:\\UserService3Impl.class"));
Thread.currentThread().setContextClassLoader(classLoader);
Class<?> userClass = null;
try {
userClass = classLoader.loadClass("com.sample.mybatis.service.impl.UserService3Impl");
System.out.println(userClass);
UserService3 userObj = (UserService3) userClass.newInstance();
System.out.println(Thread.currentThread().getName() + " ==> " + userObj.getUserNo());
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
thread.join();
Thread thread2 = new Thread(() -> {
try {
Class<?> userClass = Thread.currentThread().getContextClassLoader().loadClass("com.sample.mybatis.service.impl.UserService3Impl");
System.out.println(userClass);
UserService3 userObj = (UserService3) userClass.newInstance();
System.out.println(Thread.currentThread().getName() + " ==> " + userObj.getUserNo());
} catch (Exception e) {
e.printStackTrace();
}
});
thread2.start();
}
}運(yùn)行結(jié)果:

總結(jié):如果一個(gè)線程加載的Class,其他線程是不可以使用該Class
怎么使用ContextClassLoader才是正確姿勢呢?
ClassLoader ccl = Thread.currentThread().getContextClassLoader(); //取出
try {
MyClassLoader classLoader = new MyClassLoader();
classLoader.setClassFile(new File("D:\\UserService3Impl.class"));
Thread.currentThread().setContextClassLoader(classLoader); //設(shè)置
//其他邏輯。。。
}finally {
Thread.currentThread().setContextClassLoader(ccl); //還原
}到此這篇關(guān)于關(guān)于使用ContextClassLoader遇到的問題的文章就介紹到這了,更多相關(guān)ContextClassLoader使用詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
idea沒有services窗口、沒有springboot啟動項(xiàng)問題
這篇文章主要介紹了idea沒有services窗口、沒有springboot啟動項(xiàng)問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
JAVA利用接口實(shí)現(xiàn)多繼承問題的代碼實(shí)操演示
Java語言并不支持多繼承,這是由于多繼承會帶來許多復(fù)雜的問題,例如"菱形問題"等,下面這篇文章主要給大家介紹了關(guān)于JAVA利用接口實(shí)現(xiàn)多繼承問題的相關(guān)資料,需要的朋友可以參考下2024-03-03
SpringBoot實(shí)現(xiàn)郵件推送的詳細(xì)代碼
在項(xiàng)目中經(jīng)常會遇到SpringBoot推送消息的業(yè)務(wù),除了站內(nèi)推送通知,郵件推送也是一種常見的方式,本文小編就帶大家實(shí)現(xiàn)郵件推送,文中有詳細(xì)代碼講解,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-04-04
PostMan傳@RequestParam修飾的數(shù)組方式
這篇文章主要介紹了PostMan傳@RequestParam修飾的數(shù)組方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Java基礎(chǔ)鞏固小項(xiàng)目點(diǎn)菜系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了一個(gè)Java小項(xiàng)目點(diǎn)菜系統(tǒng)的實(shí)現(xiàn),主要是用的集合,適合正在學(xué)習(xí)Java的朋友拿來實(shí)戰(zhàn)練手,感興趣的朋友快來看看吧2022-03-03

