Java笔记 - 黑马程序员_07(多线程,线程同步,线程池,网络编程入门,UDP通信原理,TCP通信原理,commons-io工具类)
1. 實現多線程
1.1 進程
進程:是正在運行的程序
- 是系統進行資源分配鄭調用的獨立單位
- 每一個進程都有它自己的內存空間和系統資源
1.2 線程
線程:是進程中的單個順序控制流,是一條執行路徑
- 單線程:一個進程如果只有一條執行路徑,則稱為單線程程序
- 多線程:一個進程如果有多條執行路徑,則稱為多線程程序
舉例:
- 記事本程序
- 掃雷程序
1.3 多線程的實現方式(方式1)
方式1:繼承Thread類
- 定義一個類MyThread繼承Thread類
- 在MyThread類中重寫run()方法
- 創建MyThread類的對象
- 啟動線程
兩個小問題:
- 為什么要重寫run() 方法?
因為run() 是用來封裝被線程執行的代碼
- run() 方法和start() 方法的區別?
run() :封裝線程執行的代碼,直接調用,相當于普通方法的調用
start():啟動線程;然后由JVM調用此線程的run()方法
1.4 設置和獲取線程名稱
Thread類中設置和獲取線程名稱的方法
- void setName(String name):將此線程的名稱更改為等于參數name
- String getName() :返回此線程的名稱
- 通過構造方法也可以設置線程名稱
如何獲取main() 方法所在的線程名稱?
- public static Thread currentThread() 返回對當前正在執行的線程對象的引用
1.5 線程調度
線程有兩種調度模型
- 分時調度模型:所有線程輪流使用CPU的使用權,平均分配每個線程占用CPU的時間片
- 搶占式調度模型:優先讓優先級高的線程使用CPU,如果線程的優先級相同,那么會隨機選擇一個,優先級高的線程獲取的CPU時間片相對多一些
- Java使用的是搶占式調度模型
假如計算機只有一個CPU,那么CPU在某一個時刻只能執行一條指令,線程只有得到CPU時間片,也就是使用權,
才可以執行指令。所以說多線程程序的執行是有隨機性,因為誰搶到CPU的使用權是不一定的
Thread類中設置和獲取線程優先級的方法
- public final int getPriority() :返回此線程的優先級
- public final void setPriority(int newPriority):更改此線程的優先級
1.6 線程控制
| static void sleep(long millis) | 使當前正在執行的線程停留(暫停執行)指定的毫秒數 |
| void join() | 等待這個線程死亡 |
| void setDaemon(boolean on) | 將此線程標記為守護線程,當運行的線程都是守護線程時,Java虛擬機將退出 |
static void sleep(long millis) 使當前正在執行的線程停留(暫停執行)指定的毫秒數
//1. package demo_04;public class ThreadSleep extends Thread {public ThreadSleep() {}public ThreadSleep(String name) {super(name);}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName() + ":" + i);try {//static void sleep(long millis)使當前正在執行的線程以指定的毫秒數暫停(暫時停止執行),具體取決于系統定時器和調度程序的精度和準確性Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}} }//2. package demo_04;//static void sleep(long millis)使當前正在執行的線程以指定的毫秒數暫停(暫時停止執行),具體取決于系統定時器和調度程序的精度和準確性public class ThreadSleepDemo {public static void main(String[] args) {ThreadSleep ts1 = new ThreadSleep("曹操");ThreadSleep ts2 = new ThreadSleep("劉備");ThreadSleep ts3 = new ThreadSleep("孫權");ts1.start();ts2.start();ts3.start();} }void join() 等待這個線程死亡
//1. package demo_04;public class ThreadJoin extends Thread{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName()+":"+i);}} }//2. package demo_04; //void join() 等待這個線程死亡 public class ThreadJoinDemo {public static void main(String[] args) {//創建線程類對象ThreadJoin tj1 = new ThreadJoin();ThreadJoin tj2 = new ThreadJoin();ThreadJoin tj3 = new ThreadJoin();tj1.setName("張三");tj2.setName("李四");tj3.setName("王五");tj1.start();try {//void join() 等待這個線程死亡tj1.join();} catch (InterruptedException e) {e.printStackTrace();}tj2.start();tj3.start();} }void setDaemon(boolean on) 將此線程標記為守護線程,當運行的線程都是守護線程時,Java虛擬機將退出
//1. package demo_04;public class ThreadDaemon extends Thread{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println();}} }//2. package demo_04; //void setDaemon(boolean on) 將此線程標記為守護線程,當運行的線程都是守護線程時,Java虛擬機將退出 public class ThreadDaemonDemo {public static void main(String[] args) {ThreadDaemon td1 = new ThreadDaemon();ThreadDaemon td2 = new ThreadDaemon();td1.setName("關羽");td1.setName("張飛");//設置主線程為劉備Thread.currentThread().setName("劉備");//設置守護線程td1.setDaemon(true);td2.setDaemon(true);for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}} }1.7 線程生命周期
1.8 多線程的實現方式(方式2)
方式2:實現Runnable接口
- 定義一個類MyRunnable實現Runnablef接口
- 在MyRunnable類中重寫run()方法
- 創建MyRunnable類的對象
- 創建Thread類的對象,把MyRunnable對像作為構造方法的參數
- 啟動線程
多線程的實現方案有兩種
- 繼承Thread類
- 實現Runnable接口
相比繼承Thread類,實現Runnablef接口的好處
- 避免了Java單繼承的局限性
- 適合多個相同程序的代碼去處理同一個資源的情況,把線程和程序的代碼、數據有效分離,較好的體現了面向對象的設計思想
2. 線程同步
案例:賣票
需求:某電影院目前正在上映國產大片,共有100張票,而它有3個窗口賣票,請設計一個程序模擬該電影院賣票
思路:
①定義一個類SellTicket實現Runnablef接口,里面定義一個成員變量:private int tickets=100;
②在SellTicket類中重寫run() 方法實現賣票,代碼步驟如下:
A:判斷票數大于0,就賣票,并告知是哪個窗口賣的
B:賣了票之后,總票數要減1
C:票沒有了,也可能有人來問,所以這里用死循環讓賣票的動作一直執行
③定義一個測試類SellTicketDemo,里面有main方法,代碼步驟如下
A:創建SellTicket類的對象
B:創建三個Thread類的對象,把SellTicket對象作為構造方法的參數,并給出對應的窗口名稱
C:啟動線程
2.1 買票案例的思考
剛才講解了電影院賣票程序,好像沒有什么問題。但是在實際生活中,售票時出票也是需要時間的所以,在出售一張票的時候,需要一點時間的延遲,接下來我們去修改賣票程序中賣票的動作:每次出票時間100毫秒,用sleep() 方法實現
賣票出現了問題:
問題原因:
- 線程執行的隨機性導致的
2.2 賣票案例數據安全問題解決
為什么出現問題?(這也是我們判斷多線程程序是否會有數據安全問題的標準)
- 是否是多線程環境
- 是否有共享數據
- 是否有多條語句操作共享數據
如何解決多線程安全問題呢?
- 基本思想:讓程序沒有安全問題的環境
怎么實現呢?
- 把多條語句操作共享數據的代碼給鎖起來,讓任意時刻只能有一個線程執行即可
- Java提供了同步代碼塊的方式來解決(如下2.3)
2.3 同步代碼塊
鎖多條語句操作共享數據,可以使用同步代碼塊實現
格式:
synchronized(任意對象){多條語句操作共享數據的代碼 }- synchronized(任意對象):就相當于給代碼加鎖了,任意對象就可以看成是一把鎖
同步的好處和弊端:
- 好處:解決了多線程的數據安全問題
- 弊端:當線程很多時,因為每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程序的運行效率
2.4 同步方法
同步方法:就是把synchronized關鍵字加到方法上
格式:
修飾符 synchronized 返回值類型 方法名(方法參數){}同步方法的鎖對象是什么呢?
- this
同步靜態方法:就是把synchronized關鍵字加到靜態方法上
格式:
修飾符 static synchronized 返回值類型 方法名(方法參數){}同步靜態方法的鎖對象是什么呢?
- 類名.class
2.5 線程安全的類
StringBuffer
- 線程安全,可變的字符序列
- 從版本JDK5開始,被StringBuilder替代。通常應該使用StringBuilder類,因為它支持所有相同的操作,但它更快,因為它不執行同步
Vector
- 從Java2平臺v1.2開始,該類改進了List接口,使其成為Java Collections Framework的成員。與新的集合實現不同,Vector被同步。如果不需要線程安全的實現,建議使用ArrayList代替Vector
Hashtable
- 該類實現了一個哈希表,它將鍵映射到值。任何非null對像都可以用作鍵或者值
- 從Java2平臺v1.2開始,該類進行了改進,實現了Map接口,使其成為Java Collections Framework的成員。
與新的集合實現不同,Hashtable被同步。如果不需要線程安全的實現,建議使用HashMap代替Hashtable
2.6 Lock鎖
雖然我們可以理解同步代碼塊和同步方法的鎖對象問題,但是我們并沒有直接看到在哪里加上了鎖,在哪里釋放了鎖,為了更清晰的表達如何加鎖和釋放鎖,JDK5以后提供了一個新的鎖對象Lock
Lock實現提供比使用synchronized() 方法和語句可以獲得更廣泛的鎖定操作
Lock中提供了獲得鎖和釋放鎖的方法:
- void lock() :獲得鎖
- void unlock() :釋放鎖
Lock是接口不能直接實例化,這里采用它的實現類ReentrantLock來實例化
ReentrantLock的構造方法:
- ReentrantLock() :創建一個ReentrantLock的實例
3 線程池
Java提供了線程池技術,讓線程可以重復利用,解決線程頻繁創建和銷毀的問題,提高運行效率。
創建線程池
Executors類是線程池的工具類,通過Executors.工具類可以創建線程池。
| static ExecutorService newFixedThreadPool(int nThreads) | 創建一個線程池,參數為池中的線程數。 |
使用線程池
- ExecutorService代表線程池,該類中提供了submit方法用于處理提交的任務。
- 調用submit(任務)方法時,線程池會分配池中空閑的線程去執行對應的任務。
| submit(Runnable task) | 提交Runnable類型的任務 |
| submit(Callabletask) | 提交Callable類型的任務 |
| void shutdown() | 關閉連接池 |
創建任務的兩種方式:
- 實現Runnable:接口,重寫run方法。
- 實現Callable<返回值類型>接口,重寫call方法。
3.1 線程池Runable方法(案例)
//1. package com.demo_2線程池Runnable接口;public class MyRunnable implements Runnable{@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println(name+"執行了...");} }//2.測試類 package com.demo_2線程池Runnable接口;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class Demo {public static void main(String[] args) {//創建線程數量為3的線程池ExecutorService pool = Executors.newFixedThreadPool(3);//使用線程池提交任務// submit(任務)MyRunnable mr = new MyRunnable();pool.submit(mr);pool.submit(mr);pool.submit(mr);pool.submit(mr);//線程池中的線程都是出于活躍狀態,代碼不會停止//把線程池關閉,線程會全部銷毀//pool.shutdown(); //不要關閉} }3.2 線程池Callable方法(案例)
//1. package com.demo_3Callable方法;import java.util.Random; import java.util.concurrent.Callable;public class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {String name = Thread.currentThread().getName();System.out.println(name+"執行了....");Random r = new Random();int i = r.nextInt(10);System.out.println(i);return i;} }//2.測試類 package com.demo_3Callable方法;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future;public class CallableDemo {public static void main(String[] args) throws Exception {//創建線程池ExecutorService pool = Executors.newFixedThreadPool(3);//提交MyCallable任務MyCallable mc = new MyCallable();//線程池執行任務,并把返回值裝到future中Future<Integer> f = pool.submit(mc);//通過future的get方法,獲取返回值Integer a = f.get();System.out.println("a="+a);//關閉線程池(不建議使用,線程池關閉線程里的東西全部銷毀)pool.shutdown();} }案例:使用線程池完成求和計算
需求:使用線程池方式創建兩個線程任務:分段計算1~20000之間的數字和。
1.線程1計算1~10000之間的數字和,并返回結果。
2.線程2計算10001~20000之間的數字和,并返回結果。
3.提交任務,獲取計算結果進行合并,打印最終結果。
分析:因為要返回求和結果,使用Callable來實現。
4. 網絡編程入門
4.1 網絡編程概述
計算機網絡
- 是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備,通過通信線路連接起來,在網絡操作系統,網絡管理軟件及網絡通信協議的管理和協調下,實現資源共享和信息傳遞的計算機系統
網絡編程
- 在網絡通信協議下,實現網絡互連的不同計算機上運行的程序間可以進行數據交換
4.2 網絡編程三要素
IP地址
- 要想讓網絡中的計算機能夠互相通信,必須為每臺計算機指定一個標識號,通過這個標識號來指定要接收數據的計算機和識別發送的計算機,而P地址就是這個標識號。也就是設備的標識
端口
- 網絡的通信,本質上是兩個應用程序的通信。每臺計算機都有很多的應用程序,那么在網絡通信時,如何區分這些應用程序呢?如果說P地址可以唯一標識網絡中的設備,那么端口號就可以唯一標識設備中的應用程序了。也就是應用程序的標識
協議
- 通過計算機網絡可以使多臺計算機實現連接,位于同一個網絡中的計算機在進行連接和通信時需要遵守一定的規則,這就好比在道路中行駛的汽車一定要遵守交通規唄則一樣。在計算機網絡中,這些連接和通信的規則被稱為網絡通信協議,它對數據的傳輸格式、傳輸速率、傳輸步驟等做了統一規定,通信雙方必須同時遵守才能完成數據交換。常見的協議有UDP協議和TCP協議
4.3 IP地址
IP地址:是網絡中設備的唯一標識
P地址分為兩大類
- IPv4:是給每個連接在網絡上的莊機分配一個32bi地址。按照TCP八P規定,P地址用二進制來表示,每個P地址長32bit,也就是4個字節。例破如一個采用二進制形式的P地址是“11000000101010000000000101000010°”,這么長的地址,處理起來也太費勁了。為了方便使用,P地址經常被寫成十進制的形式,中間使用符號“”分隔不同的字節。于是,上面的1P地址可以表示為"192.168.1.66”。P地址的這種表示法叫做“點分十進制表示法”,這顯然比1和0容易記憶得多
- IPV6:由于互聯網的蓬勃發展,P地址的需求量愈來愈大,但是網絡地址資源有限,使得P的分配越發緊張。為了擴大地址空間,通過Pv6重新定義地址空間,采用128位地址長度,每16個字節一組,分成8組十六進制數,這樣就解決了網絡地址資源數量不夠的問題
常用命令:
- ipconfig:查看本機IP地址
- ping IP地址:檢查網絡是否連通
特殊IP地址:
- 127.0.0.1:是回送地址,可以代表本機地址,般用來測試使用
4.4 InetAddress的使用
為了方便我們對lP地址的獲取和操作,Java提供了一個類InetAddress供我們使用
InetAddress:此類表示Internet協議 (IP) 地址
| static InetAddress getByName(String host) | 確定主機名稱的P地址。主機名稱可以是機器名稱,也可以是P地址 |
| String getHostName() | 獲取此P地址的主機名 |
| String getHostAddress() | 返回文本顯示中的IP地址字符串 |
4.5 端口
端口:設備上應用程序的唯一標識
端口號:用兩個字節表示的整數,它的取值范圍是065535。其中,01023之間的端口號用于一些知名的網絡服務和應用,普通的應用程序需要使用1024以上的端口號。如果端口號被另外一個服務或應用所占用,會導致當前程序啟動失敗
4.6 協議
協議:計算機網絡中,連接和通信的規則被稱為網絡通信協議
UDP協議:
- 用戶數據報協議(User Datagram Protocol)
- UDP是無連接通信協議,即在數據傳輸時,數據的發送端和接收端不建立邏輯連接。簡單來說,當一臺計算機向另外一臺計算機發送數據時,發送端不會確認接收端是否存在,就會發出數據,同樣接收端在收到數據時,也不會向發送端反饋是否收到數據。由于使用UDP協議消耗資源小,通信效率高,所以通常都會用于音頻、視頻和普通數據的傳輸
- 例如視頻會議通常采用UDP協議,因為這種情況即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。但是在使用UDP協議傳送數據時,由于UDP的面向無連接性,不能保證數據的完整性,因此在傳輸重要數據時不建議使用UDP協議
TCP協議:
- 傳輸控制協議(Transmission Control Protocol)
- TCP協議是面向連接的通信協議,即傳輸數據之前,在發送端和接收總建立邏輯連接,然后再傳輸數據,
它提供了兩臺計算機之間可靠無差錯的數據傳輸。在TCP連接中必須要明確客戶端與服務器端,由客戶端
向服務端發出連接請求,每次連接的創建都需要經過“三次握手” - 三次握手:TCP協議中,在發送數據的準備階段,客戶端與服務器之間的三次交互,以保證連接的可靠
第一次握手,客戶端向服務器端發出連接請求,等待服務器確認
第二次握手,服務器端向客戶端回送一個響應,通知客戶端收到了連接請求
第三次握手,客戶端再次向服務器端發送確認信息,確認連接 - 完成三次握手,連接建立后,客戶端和服務器就可以開始進行數據傳輸了。由于這種面向連接的特性,TCP協議可以保證傳輸數據的安全,所以應用十分廣泛。例如上傳文件、下載文件、瀏覽網頁等
5. UDP通信原理
5.1 UDP通信原理
UDP協議是一種不可靠的網絡協議,它在通信的兩端各建立一個Socket對象,但是這兩個Socket只是發送,接收數據的對象因此對于基于UDP協議的通信雙方而言,沒有所謂的客戶端和服務器的概念Java提供了DatagramSocket類作為基于UDP協議的Socket
5.2 UDP發送數據
發送數據的步驟
①創建發送端的Socket對象(DatagramSocket)
DatagramScoket()②創建數據,并把數據打包
DatagramPacket(byte[]buf,int length,InetAddress address,int port)③調用DatagramSocket對象的方法發送數據
void send(DatagramPacket p)④關閉發送端
void close() package demo_02;/* 發送數據的步驟:創建發送端的Socket對象(DatagramSocket)創建數據,并把數據打包調用DatagramSocket對象的方法發送數據關閉發送端 */import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;public class SendDemo {public static void main(String[] args) throws IOException {//創建發送端的Socket對象(DatagramSocket)//DatagramSocket()//構造數據報套接字并將其綁定到本地主機上的任何可用端口DatagramSocket ds = new DatagramSocket();//創建數據,并把數據打包//DatagramPacket(byte[] buf, int length, InetAddress address, int port)//構造用于發送長度的分組的數據報包 length指定主機上到指定的端口號byte[] bys = "hello,java".getBytes();DatagramPacket dp = new DatagramPacket(bys,bys.length, InetAddress.getByName("192.168.31.81"),10010);//調用DatagramSocket對象的方法發送數據//void send(DatagramPacket p)從此套接字發送數據報包 ds.send(dp);//關閉發送端ds.close();} }5.3 UDP接收數據
接收數據的步驟
①創建接收端的Socket對象(DatagramSocket)
DatagramSocket(int port)②創建一個數據包,用于接收數據
DatagramPacket(byte[]buf,int length)③調用DatagramSocket對象的方法接收數據
void receive(DatagramPacket p)④解析數據包,并把數據在控制臺顯示
byte[] getData() int getLength()⑤關閉接收端
void close() package demo_02; /* 接收數據的步驟:創建接收端的Socket對象(DatagramSocket)創建一個數據包,用于接收數據調用DatagramSocket對象的方法接收數據解析數據包,并把數據在控制臺顯示關閉接收端 */ import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket;public class ReceiveDemo {public static void main(String[] args) throws IOException {//創建接收端的Socket對象(DatagramSocket)DatagramSocket ds = new DatagramSocket(10010);//創建一個數據包,用于接收數據byte[] bys = new byte[1024];DatagramPacket dp = new DatagramPacket(bys,bys.length);//調用DatagramSocket對象的方法接收數據ds.receive(dp);//解析數據包,并把數據在控制臺顯示byte[] datas = dp.getData();int len = dp.getLength();System.out.println("數據是:"+new String(datas,0,len));//關閉接收端ds.close();} }5.4 UDP通信程序練習
按照下面的要求實現程序:
6. TCP通信原理
6.1 TCP通信原理
6.2 TCP發送數據
發送數據的步驟:
①創建客戶端的Socket對象(Socket)
Socket(String host,int port)②獲取輸出流,寫數據
OutputStream getOutputStream()③釋放資源
void close() package TCPDemo_04; /* 發送數據的步驟創建客戶端的Socket對象(Socket)獲取輸出流,寫數據科放資源 */ import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;public class ClientDemo {public static void main(String[] args) throws IOException {//創建客戶端的Socket對象(Socket)//Socket(InetAddress address, int port)創建流套接字并將其連接到指定IP地址的指定端口號 // Socket s = new Socket(InetAddress.getByName("192.168.31.81"),10010);//Socket(String host, int port)創建流套接字并將其連接到指定主機上的指定端口號Socket s= new Socket("192.168.31.81",10010);//獲取輸出流,寫數據//OutputStream getOutputStream()返回此套接字的輸出流OutputStream os = s.getOutputStream();os.write("hello,java".getBytes());//釋放資源s.close();} }6.3 TCP接受數據
接收數據的步驟:
①創建服務器端的Socket對象(ServerSocket)
ServerSocket(int port)②監聽客戶端連接,返回一個Socket對象
Socket accept()③獲取輸入流,讀數據,并把數據顯示在控制臺
InputStream getlnputStream()④釋放資源
void close() package TCPDemo_04; /* 接收數據的步驟:創建服務器端的Socket對象(ServerSocket)監聽客戶端連接,返回一個Sockety對象獲取輸入流,讀數據,并把數據顯示在控制臺釋放資源 */ import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;public class Serverdemo {public static void main(String[] args) throws IOException {//創建服務器端的Socket對象(ServerScoket)//ServerSocket(int port)創建綁定到指定端口的服務器套接字ServerSocket ss = new ServerSocket(10010);//監聽客戶端連接,返回一個Sockety對象Socket s = ss.accept();//獲取輸入流,讀數據,并把數據顯示在控制臺InputStream is = s.getInputStream();byte[] bys = new byte[1024];int len = is.read(bys);String data = new String(bys,0,len);System.out.println("數據是:"+data);//釋放資源ss.close();s.close();} }6.4 TCP通信程序練習
練習1
- 客戶端:發送數據,接收服務器反饋
- 服務端:接收數據,給出反饋
練習2
- 客戶端:數據來自于鍵盤錄入,直到輸入的數據是886,發送數據結束
- 服務器:接收到的數據在控制臺輸出
練習3
- 客戶端:數據來自于鍵盤錄入,直到輸入的數據是886,發送數據結束
- 服務器:接收到的數據寫入文本文件
練習4
- 客戶端:數據來自于文本文件
- 服務器:接收到的數據寫入文本文件
練習5
- 客戶端:數據來自于文本文件,接收服務器反饋
- 服務器:接收到的數據寫入文本文件,給出反饋
出現問題:程序一直等待
原因:讀數據的方法是阻塞式的
解決辦法:自定義結束標記使用shutdownOutput()方法(推薦)
練習6
- 客戶端:數據來自于文本文件,接收服務器反饋
- 服務器:接收到的數據寫入文本文件,給出反饋,代碼用線程進行封裝,為每一個客戶端開啟一個線程
commons-io工具類的使用
commons-io概述
- commons-io是apache開源基金組織提供的一組有關IO操作的類庫,可以挺提高lO功能開發的效率
- commons-io工具包提供了很多有關IO操作的類。有兩個主要的類FileUtils, IOUtils
FileUtils主要有如下方法:
| String readFileToString(File file, String encoding) | 讀取文件中的數據,返回字符串 |
| void copyFile(File srcFile, File destFile) | 復制文件 |
| void copyDirectoryToDirectory(File srcDir, File destDir) | 復制文件夾 |
commons-io使用步驟:
更多內容請訪問博主博客:逸樂的博客 - 今晚一起吃火鍋
文章如有紕漏請指出,整理不易多多包涵。
Java后續筆記將持續更新…
總結
以上是生活随笔為你收集整理的Java笔记 - 黑马程序员_07(多线程,线程同步,线程池,网络编程入门,UDP通信原理,TCP通信原理,commons-io工具类)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VBAProject调用mysql出错_
- 下一篇: Java零基础入门路径学习