搜尋
首頁Javajava教程Java多執行緒詳解

Java多執行緒詳解

May 15, 2018 am 10:38 AM
java學習筆記執行緒

多執行緒背景知識介紹

利用多執行緒可以簡化模型,寫功能強大的程式碼,但是要寫好多執行緒卻不容易,需要一個長期實踐的過程。 

多執行緒基礎概念介紹

進程與執行緒

①  進程:程式(任務)的執行過程。動態性

持有資源(共享內存,共享檔案)和線程。載體

範例:Eclipse、QQ

②  執行緒:

Eclipse:原始碼文字編輯、原始碼編譯、語法校驗。

QQ:文字聊天、收發檔案。

如果把行程比喻成一個班級,那麼這個班級中的每一個學生就是線程。學生是班級當中的最小單元,構成班級當中的最小單位。一個班級可以有多個學生,這些學生都使用班級當中共同的桌椅、黑板、粉筆。

線程是系統中最小的執行單元,同一個進程中有多個線程,線程共享進程的資源。

執行緒的互動

互斥、同步。

Java線程初步體驗

Java.lang

class Thread

interface Runnable

public void run ()

執行緒的常用方法

## Thread(Runnable target,String name) 執行緒的方法執行緒休眠static void sleep(long millis,int nanos)使其他執行緒等待目前執行緒終止void join(long millis,int nanos)

#方法簽章

簡介

#執行緒的建立

Thread()

 

#Thread(String name)

 

#Thread(Runnable target)

void start()

啟動執行緒

static void sleep(long millis)

void join()

void join( long millis)

#########static void yield()############目前執行緒釋放處理器資源################### 取得執行緒參考####### #####static Thread currentThread()############傳回目前執行的執行緒參考###############

兩個執行緒不做任何處理的時候,會交替運行。

當使用boolean類型控制執行緒的循環時,要在變數前面加上volatile關鍵字,volatile保證了執行緒可以正確的讀取其他執行緒寫入的值。

注意點:

sleep()方法的作用:使執行緒休眠指定的時間。

join()方法的作用: //使其他執行緒等待目前執行緒執行完畢。

多執行緒案例

範例1:

1 package com.czgo;  
2   
3    
4   
5 /**  
6   
7  * 线程先生  
8   
9  * @author 疯子 
10  
11  * 
12  
13  */ 
14  
15 public class Actor extends Thread { 
16  
17     @Override 
18  
19     public void run() { 
20  
21         //getName():获取当前线程的名称 
22  
23         System.out.println(getName()+"是一个演员!"); 
24  
25         //用来记录线程跑的次数 
26  
27         int count = 0; 
28  
29         boolean keepRunning = true; 
30  
31         while(keepRunning){ 
32  
33             System.out.println(getName()+"登台演出"+(++count)); 
34  
35             if(count==100){ 
36  
37                 keepRunning = false; 
38  
39             } 
40  
41             if(count%10==0){ 
42  
43                 try { 
44  
45                     Thread.sleep(1000); 
46  
47                 } catch (InterruptedException e) { 
48  
49                     e.printStackTrace(); 
50  
51                 } 
52  
53             } 
54  
55         } 
56  
57         System.out.println(getName()+"的演出结束了!"); 
58  
59     } 
60  
61     
62  
63     public static void main(String[] args) { 
64  
65         Thread actor = new Actor(); 
66  
67         //setName:设置线程的名称 
68  
69         actor.setName("Mr.Thread"); 
70  
71         //启动线程 
72  
73         actor.start(); 
74  
75         
76  
77         Thread actressThread = new Thread(new Actress(),"Ms.Runnable"); 
78  
79         actressThread.start(); 
80  
81     } 
82  
83 } 
84  
85   
86  
87 class Actress implements Runnable{ 
88  
89     @Override 
90  
91     public void run() { 
92  
93         //getName():获取当前线程的名称 
94  
95         //currentThread()获取当前线程的引用 
96  
97         System.out.println(Thread.currentThread().getName()+"是一个演员!"); 
98  
99         //用来记录线程跑的次数
100 
101         int count = 0;
102 
103         boolean keepRunning = true;
104 
105         while(keepRunning){
106 
107             System.out.println(Thread.currentThread().getName()+"登台演出"+(++count));
108 
109             if(count==100){
110 
111                 keepRunning = false;
112 
113             }
114 
115             if(count%10==0){
116 
117                 try {
118 
119                     Thread.sleep(1000);
120 
121                 } catch (InterruptedException e) {
122 
123                     e.printStackTrace();
124 
125                 }
126 
127             }
128 
129         }
130 
131         System.out.println(Thread.currentThread().getName()+"的演出结束了!");   
132 
133     }134 135 }

範例2:

軍隊:

 1 package com.czgo; 
 2  
 3   
 4  
 5 /** 
 6  
 7  * 军队线程 
 8  
 9  * 模拟作战双方的行为
 10 
 11  * @author 疯子
 12 
 13  *
 14 
 15  */
 16 
 17 public class ArmyRunnable implements Runnable {
 18 
 19    
 20 
 21     //volatile保证了线程可以正确的读取其他线程写入的值
 22 
 23     //可见性 ref JMM,happens-before
 24 
 25     volatile boolean keepRunning = true;
 26 
 27    
 28 
 29     @Override
 30 
 31     public void run() {
 32 
 33        
 34 
 35         while(keepRunning){
 36 
 37             //发动5连击
 38 
 39             for(int i=0;i<5;i++){
 40 
 41                 System.out.println(Thread.currentThread().getName()+"进攻对方["+i+"]");
 42 
 43                 //让出了处理器时间,下次谁进攻还不一定呢!
 44 
 45                 Thread.yield();
 46 
 47             }
 48 
 49         }
 50 
 51        
 52 
 53         System.out.println(Thread.currentThread().getName()+"结束了战斗!");
 54 
 55        
 56 
 57     }
 58 
 59 }

關鍵人物:

1 package com.czgo; 
2  
3   
4  
5 /** 
6  
7  * 关键人物 
8  
9  * @author 疯子
10 
11  *
12 
13  */
14 
15 public class KeyPersonThread extends Thread {
16 
17     @Override
18 
19     public void run() {
20 
21         System.out.println(Thread.currentThread().getName()+"开始了战斗!"); 
22 
23         for(int i=0;i<10;i++){
24 
25             System.out.println(Thread.currentThread().getName()+"左突右杀,攻击随军...");
26 
27         }
28 
29         System.out.println(Thread.currentThread().getName()+"结束了战斗!");
30 
31  
32 
33     }
34 
35 }

舞台:

  1 package com.czgo;  
  2   
  3    
  4   
  5 /**  
  6   
  7  * 隋唐演义大戏舞台  
  8   
  9  * @author win7 
  10  
  11  * 
  12  
  13  */ 
  14  
  15 public class Stage extends Thread { 
  16  
  17     
  18  
  19     @Override 
  20  
  21     public void run() { 
  22  
  23         System.out.println("欢迎观看隋唐演义"); 
  24  
  25         
  26  
  27         try { 
  28  
  29             Thread.sleep(5000); 
  30  
  31         } catch (InterruptedException e2) { 
  32  
  33             e2.printStackTrace(); 
  34  
  35         } 
  36  
  37         
  38  
  39         System.out.println("大幕徐徐拉开"); 
  40  
  41         
  42  
  43         try { 
  44  
  45             Thread.sleep(5000); 
  46  
  47         } catch (InterruptedException e2) { 
  48  
  49             e2.printStackTrace(); 
  50  
  51         } 
  52 
  53         
  54  
  55         System.out.println("话说隋朝末年,隋军与农民起义军杀得昏天暗地..."); 
  56  
  57         
  58  
  59         //隋朝军队 
  60  
  61         ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable(); 
  62 
  63         //农民起义军 
  64  
  65         ArmyRunnable armyTaskOfRevolt = new ArmyRunnable(); 
  66  
  67         
  68  
  69         //使用Runnable接口创建线程 
  70  
  71         Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军"); 
  72  
  73         Thread armyOfSuiRevolt = new Thread(armyTaskOfRevolt,"农民起义军"); 
  74  
  75         
  76  
  77         //启动线程,让军队开始作战 
  78  
  79         armyOfSuiDynasty.start(); 
  80  
  81         armyOfSuiRevolt.start(); 
  82  
  83         
  84  
  85         //舞台线程休眠,大家专心观看军队的厮杀 
  86  
  87         try { 
  88  
  89             //Thread会指向当前类的线程 
  90 
  91             Thread.sleep(50); 
  92  
  93         } catch (InterruptedException e) { 
  94  
  95             e.printStackTrace(); 
  96  
  97         } 
  98
  99         System.out.println("正当双方激战正酣,半路杀出了个程咬金");
  100 
  101        
  102 
  103         Thread mrCheng = new KeyPersonThread();
  104 
  105         mrCheng.setName("程咬金");
  106 
  107        
  108 
  109         System.out.println("程咬金的理想就是结束战争,使百姓安居乐业!");
  110 
  111        
  112 
  113         //停止军队作战
  114 
  115         //停止线程的方法
  116 
  117         armyTaskOfSuiDynasty.keepRunning=false;
  118 
  119         armyTaskOfRevolt.keepRunning=false;
  120 
  121       
  122 
  123         try {
  124 
  125             Thread.sleep(2000);
  126 
  127         } catch (InterruptedException e1) {
  128 
  129             e1.printStackTrace();
  130 
  131         }
  132 
  133        134 135         //历史大戏留给关键人物
  136 
  137         mrCheng.start();
  138 
  139        
  140 
  141         try {
  142 
  143             //使其他线程等待当前线程执行完毕
  144 
  145             mrCheng.join();
  146 
  147         } catch (InterruptedException e) {
  148 
  149             e.printStackTrace();150 151         }
  152 
  153        
  154 
  155         System.out.println("战争结束,人民安居乐业,程先生实现了积极的人生梦想,为人民作出了贡献!");
  156 
  157         System.out.println("谢谢观看隋唐演义,再见!");
  158 
  159     }
  160 
  161    
  162 
  163     public static void main(String[] args) {
  164 
  165         new Stage().start();
  166 
  167     }
  168 
  169 }

執行緒的正確停止

##如何正確的停止Java中的執行緒:

可以透過boolean類型來控制循環的退出。

not stop方法

stop()方法會讓執行緒戛然而止。

stop()方法停止執行緒是錯誤的方法。

線程的互動

爭用條件Race Condition

當多個執行緒同時共享存取相同資料(記憶體區域)時,每個執行緒都嘗試操作該數據,從而導致數據被破壞(corrupted),這種現象稱為爭用條件。

什麼是互斥?

互斥是怎麼實現的?

只能被一個執行緒所訪問,互斥。

互斥的實作:synchronized(intrinsic lock)加鎖。

同步的實作:wait()/notify()/notifyAll()。

如何擴展Java並發的知識

Java Memory Mode

         JMM描述了Java執行緒如何透過記憶體互動

    -before

         Synchronized,volatile&final

Locks&Condition

        ##線程安全性

         原子性與可見性

         Java.util.concurrent.atomic

#o 

##多線程編程常用的交互模型

         Producer-Consumer模型

         Read-Write Lock模型

         Future模型

         Worker Thread模型

Java5中並發程式設計工具

         Java.util.concurrent

         執行緒池ExecutorService

#推薦兩本書:

Core Java

Java concurrency in practice

#執行緒所建立的兩種方式比較

Thread:

#①  繼承Thread類別;

Runnable:

①  Runnable方式可避免Thread方式因Java單一繼承特性所帶來的缺陷。

②  Runnable的程式碼可以被多個執行緒(Thread實例)共享,適合於多個執行緒處理相同資源的情況。

案例:

Thread:

 1 package com.czgo; 
 2  
 3   
 4  
 5 class MyThread extends Thread{ 
 6  
 7     
 8  
 9     private int ticketsCont = 5;    //一共有5张火车票
 10 
 11    
 12 
 13     private String name;            //窗口,也即是线程的名字
 14 
 15    
 16 
 17     public MyThread(String name){
 18 
 19         this.name = name;
 20 
 21     }
 22 
 23    24 25     @Override
 26 
 27     public void run() {
 28 
 29        30 31         while(ticketsCont>0){
 32 
 33             ticketsCont--;      //如果还有票,就卖掉一张
 34 
 35             System.out.println(name+"卖了1张票,剩余票数为:"+ticketsCont);
 36 
 37         }
 38 
 39     }
 40 
 41    
 42 
 43 }
 44 
 45  
 46 
 47 public class TicketsThread {
 48 
 49  
 50 
 51     public static void main(String[] args) {
 52 
 53         //创建3个线程,模拟三个窗口卖票
 54 
 55         MyThread mt1 = new MyThread("窗口1");
 56 
 57         MyThread mt2 = new MyThread("窗口2");
 58 
 59         MyThread mt3 = new MyThread("窗口3");
 60 
 61        62 63         //启动这三个线程,也即是窗口,开始卖票
 64 
 65         mt1.start();
 66 
 67         mt2.start();
 68 
 69         mt3.start();
 70 
 71        
 72 
 73     }
 74 
 75  
 76 
 77 }

Runnable:

 1 package com.czgo; 
 2  
 3   
 4  
 5 class MyThread implements Runnable{ 
 6  
 7     
 8  
 9     private int ticketsCont = 5;    //一共有5张火车票
 10 
 11  
 12 
 13     @Override
 14 
 15     public void run() {
 16 
 17        
 18 
 19         while(ticketsCont>0){
 20 
 21             ticketsCont--;      //如果还有票,就卖掉一张
 22 
 23             System.out.println(Thread.currentThread().getName()+"卖了1张票,剩余票数为:"+ticketsCont);
 24 
 25         }
 26 
 27        
 28 
 29     }
 30 
 31    
 32 
 33 }
 34 
 35  
 36 
 37 public class TicketsRunnable {
 38 
 39  
 40 
 41     public static void main(String[] args) {
 42 
 43        
 44 
 45         MyThread mt1 = new MyThread();
 46 
 47         MyThread mt2 = new MyThread();
 48 
 49         MyThread mt3 = new MyThread();
 50 
 51        
 52 
 53         //创建三个线程来模拟三个售票窗口
 54 
 55         Thread th1 = new Thread(mt1,"窗口1");
 56 
 57         Thread th2 = new Thread(mt2,"窗口2");
 58 
 59         Thread th3 = new Thread(mt3,"窗口3");
 60 
 61        
 62 
 63         //启动这三个线程,也即是三个窗口开始卖票
 64 
 65         th1.start();
 66 
 67         th2.start();
 68 
 69         th3.start();
 70 
 71  
 72 
 73     }
 74 
 75  
 76 
 77 }

執行緒的生命週期

##圖示:

 

建立:新建一個執行緒對象,如Thread thd = new Thread()。

就緒:創建了線程物件後,呼叫了線程的start()方法(注意:此時線程只是進入了線程隊列,等待獲取cpu服務,具備了運行的條件,但不一定已經開始運行了)。

運行:處於就緒狀態的線程,一旦取得了CPU資源,便進入到運行狀態,開始執行run()方法裡面的邏輯。

終止:執行緒的run()方法執行完畢,或是執行緒呼叫了stop()方法,執行緒便進入終止狀態。

阻塞:正在執行的線程在某些情況下,由於某種原因而暫時讓出了CPU資源,暫停了自己的執行,便進入了阻塞狀態,如調用了sleep()方法。

 

線程的守護神-守護線程

#Java線程有兩類:

用戶執行緒:運行在前台,執行具體的任務。

例如程式的主執行緒、連接網路的子執行緒等都是使用者執行緒。

 

守護執行緒:運行在後台,為其他前台執行緒服務。 特點:一旦所有使用者執行緒都結束運行,守護執行緒就會隨JVM一起結束工作。

應用程式:資料庫連線池中的監控執行緒、JVM虛擬機啟動後的監控執行緒。 最常見的守護線程:垃圾回收線程。

如何设置守护线程

可以通过调用Thread类的setDaemon(true)方法来设置当前线程为守护线程。

注意事项:

setDaemon(true)必须在start()方法之前调用,否则会抛出IllegalThreadStateException异常。

在守护线程中产生的新线程也是守护线程

不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑。

案例:

  1 package com.czgo;  
  2   
  3    
  4   
  5 import java.io.File;  
  6   
  7 import java.io.FileOutputStream;  
  8   
  9 import java.io.IOException; 
  10  
  11 import java.io.OutputStream; 
  12  
  13 import java.util.Scanner; 
  14  
  15   
  16  
  17 class DaemonThread implements Runnable{ 
  18  
  19     @Override 
  20  
  21     public void run() { 
  22  
  23         System.out.println("进入守护线程"+Thread.currentThread().getName()); 
  24  
  25         try { 
  26  
  27             writeToFile(); 
  28  
  29         } catch (IOException e) { 
  30  
  31             e.printStackTrace(); 
  32  
  33         } catch (InterruptedException e) { 34  35             e.printStackTrace(); 
  36  
  37         } 
  38  
  39         System.out.println("退出守护线程"+Thread.currentThread().getName()); 
  40  
  41         
  42  
  43     } 
  44  
  45     
  46  
  47     private void writeToFile() throws IOException, InterruptedException{ 
  48  
  49         File filename = new File("C:\\ide"+File.separator+"daemon.txt"); 
  50  
  51         OutputStream os = new FileOutputStream(filename,true); 
  52  
  53         int count = 0; 
  54  
  55         while(count<999){ 
  56  
  57             os.write(("\r\nword"+count).getBytes()); 
  58  
  59             System.out.println("守护线程"+Thread.currentThread().getName()+"向文件中写入了word"+count++); 
  60 
  61             Thread.sleep(1000); 
  62  
  63         } 
  64  
  65         os.close(); 
  66  
  67     } 
  68  
  69 } 
  70  
  71   
  72  
  73 public class DaemonThreadDemo { 
  74  
  75   
  76  
  77     public static void main(String[] args) { 
  78  
  79         
  80  
  81         System.out.println("进入主线程"+Thread.currentThread().getName()); 
  82  
  83         DaemonThread daemonThread = new DaemonThread(); 
  84  
  85         Thread thread = new Thread(daemonThread); 
  86  
  87         thread.setDaemon(true); 
  88  
  89         thread.start(); 
  90  
  91         
  92  
  93         Scanner sc = new Scanner(System.in); 
  94  
  95         sc.next();
  96  
  97         
  98  
  99         System.out.println("退出主线程"+Thread.currentThread().getName());
  100 
  101     }
  102 
  103  
  104 
  105 }


使用jstack生成线程快照

jstack

作用:生成jvm当前时刻线程的快照(threaddump,即当前进程中所有线程的信息)

目的:帮助定位程序问题出现的原因,如长时间停顿、cpu占用率过高等。

如何使用jstack

jstack –l pid

 

内存可见性

可见性介绍

可见性:一个线程对共享变量值的修改,能够及时地被其他线程看到。

共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。

Java内存模型(JMM)

Java内存模型(Java Memory Model)描述了程序中各种变量(线程共享变量)的访问规则,以及在Java中将变量存储到内存和从内存中读取出变量这样的底层细节。

所有变量都存储在主内存中

每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存中该变量的一份拷贝)。

 

线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接从主内存中读写。

不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。

共享变量可见性实现的原理

线程1对共享变量的修改要想被线程2及时看到,必须要经过如下2个步骤:

把工作内存1中更新过的共享变量刷新到主内存中。

将主内存中最新的共享变量的值更新到工作内存2中。

可见性

要实现共享变量的可见性,必须保证两点:

线程修改后的共享变量值能够及时从工作内存刷新到主内存中。

其他线程能够及时把共享变量的最新值从主内存更新到自己的工作内存中。

可见性的实现方式

Java语言层面支持的可见性实现方式:

Synchronized

Volatile

Synchronized实现可见性

Synchronized能够实现:

原子性(同步);

可见性

JMM关于Synchronized的两条规定:

线程解锁前,必须把共享变量的最新值刷新到主内存中;

线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意:加锁与解锁需要是同一把锁)

线程解锁前对共享变量得修改在下次加锁时对其他线程可见。

线程执行互斥代码的过程:

  1. 获得互斥锁

  2. 清空工作内存

  3. 从主内存中拷贝变量的最新副本到工作内存

  4. 执行代码。

  5. 将更改后的共享变量的值刷新到主内存。

  6. 释放互斥锁。

重排序

重排序:代码书写的顺序与实际执行的顺序不同,指令重排序是编译器或处理器为了提高程序性能而做的优化。

  1. 编译器优化的重排序(编译器优化)。

  2. 指令级并行重排序(处理器优化)。

  3. 内存系统的重排序(处理器优化)。

as-if-serial

as-if-serial:无论如何重排序,程序执行的结果应该与代码顺序执行的结果一致(java编译器、运行时和处理器都会保证Java在单线程下遵循as-if-serial语义)。

例子:

Int num = 1;

Int num2 = 2;

Int sum = num+num2;

单线程:第1、2行的顺序可以重排,但第3行不能

重排序不会给单线程带来内存可见性问题

多线程中程序交错执行时,重排序可能会造成内存可见性问题。

Volatile实现可见性

Volatile关键字:

能够保证volatile变量的可见性

不能保证volatile变量复合操作的原子性

Volatile如何实现内存可见性:

深入來說:透過加入記憶體屏障和禁止重排序優化來實現的。

對volatile變數執行寫入作業時,會在寫入作業後加入一個store屏障指令

#對volatile變數執行讀取操作時,會在讀取操作前加入load屏障指令

通俗的講:volatile變數在每次被執行緒存取時,都強迫從主記憶體重讀該變數的值,而當該變數發生變化時,又會強迫執行緒將最新的值刷新到主記憶體。這樣任何時刻,不同執行緒總是能看到該變數的最新值。

線程寫volatile變數的過程:

  1. 改變線程工作記憶體中volatile變數副本的值

  2. ##將改變後的副本的值從工作記憶體刷新到主記憶體

線程讀取volatile變數的過程:

  1. 從主記憶體讀取volatile變量的最新值到線程的工作記憶體中

  2. 從工作記憶體讀取volatile變數的副本。

Volatile適用場合

要在多執行緒中安全的使用volatile變量,必須同時滿足:

1. 對變數的寫入操作不依賴其目前值

2.  布爾,用來記錄溫度

3.該變數沒有包含在具有其他變數的不變式中。

結語:不要在意別人在背後怎麼看你說你,因為這些言語改變不了事實,卻可能會攪亂你的心。

以上是Java多執行緒詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。