關(guān)于使用ContextClassLoader遇到的問題
關(guān)于使用ContextClassLoader遇到的問題
對(duì)ContextClassLoader有一些疑惑:
- 父線程加載的Class,子線程是否可以使用該Class? 答:可以
- 子線程加載的Class,父線程是否可以使用該Class? 答:不可以
- 如果一個(gè)線程加載的Class,其他線程是否可以使用該Class ? 答:不可以
- 怎么使用ContextClassLoader才是正確姿勢(shì)呢? 答:取出->更改->還原(finally語句塊)。
關(guān)于上述4點(diǎn)疑問,做了以下測(cè)試:
父線程加載的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?
測(cè)試代碼:
/** * 如果兩個(gè)線程不是父子線程, 線程之間不會(huì)共享加載過的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才是正確姿勢(shì)呢?
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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java synchronized關(guān)鍵字和Lock接口實(shí)現(xiàn)原理
這篇文章主要介紹了Java synchronized關(guān)鍵字和Lock接口實(shí)現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Java并發(fā)編程線程間通訊實(shí)現(xiàn)過程詳解
這篇文章主要介紹了Java并發(fā)編程線程間通訊實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05SpringBoot通過@Value實(shí)現(xiàn)給靜態(tài)變量注入值詳解
這篇文章主要介紹了springboot如何通過@Value給靜態(tài)變量注入值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07