CodeGym /หลักสูตร /All lectures for TH purposes /งบทดลองกับทรัพยากร

งบทดลองกับทรัพยากร

All lectures for TH purposes
ระดับ , บทเรียน
มีอยู่

"อามิโกะ เท็นฮัท!"

"ฉันมีความสุขที่ได้เรียน Java กัปตัน!"

"สบายใจได้ Amigo วันนี้เรามีหัวข้อที่น่าสนใจมาก เราจะพูดถึงวิธีที่โปรแกรม Java โต้ตอบกับทรัพยากรภายนอก และเราจะศึกษาคำสั่ง Java ที่น่าสนใจมาก อย่าปิดหูไว้ดีกว่า"

"ฉันหูทั้งหมด"

"ขณะที่โปรแกรม Java ทำงาน บางครั้งโปรแกรมจะโต้ตอบกับเอนทิตีภายนอกเครื่อง Java เช่น กับไฟล์บนดิสก์ เอนทิตีเหล่านี้มักเรียกว่าทรัพยากรภายนอก"

“แล้วอะไรล่ะที่ถือว่าเป็นทรัพยากรภายใน?”

"ทรัพยากรภายในคือวัตถุที่สร้างขึ้นภายในเครื่อง Java โดยทั่วไปแล้ว การโต้ตอบเป็นไปตามโครงร่างนี้:

งบทดลองกับทรัพยากร

"ระบบปฏิบัติการติดตามทรัพยากรที่มีอยู่อย่างเข้มงวด และยังควบคุมการเข้าถึงร่วมกันจากโปรแกรมต่างๆ ตัวอย่างเช่น ถ้าโปรแกรมหนึ่งเปลี่ยนไฟล์ โปรแกรมอื่นจะไม่สามารถเปลี่ยนแปลง (หรือลบ) ไฟล์นั้นได้ หลักการนี้ไม่ใช่ จำกัด เฉพาะไฟล์ แต่ให้ตัวอย่างที่เข้าใจได้ง่ายที่สุด

"ระบบปฏิบัติการมีฟังก์ชัน (API) ที่อนุญาตให้โปรแกรมรับและ/หรือปล่อยทรัพยากร หากทรัพยากรไม่ว่าง เฉพาะโปรแกรมที่ได้รับมาเท่านั้นที่สามารถทำงานได้ ถ้าทรัพยากรนั้นว่าง โปรแกรมใดๆ ก็สามารถรับได้ มัน.

"ลองนึกภาพว่าสำนักงานมีแก้วกาแฟร่วมกัน ถ้ามีคนเอาแก้วไป คนอื่นจะรับไม่ได้อีกต่อไป แต่เมื่อแก้วถูกใช้งาน ล้าง และใส่กลับเข้าที่แล้ว ใครๆ ก็หยิบได้อีก"

"เข้าใจแล้ว มันก็เหมือนกับที่นั่งบนรถไฟใต้ดินหรือระบบขนส่งสาธารณะอื่นๆ ถ้าที่นั่งว่าง ใครก็นั่งได้ ถ้าที่นั่งว่าง คนที่นั่งก็จะเป็นคนควบคุม"

"ถูกต้อง และตอนนี้เรามาพูดถึงการรับทรัพยากรภายนอกทุกครั้งที่โปรแกรม Java ของคุณเริ่มทำงานกับไฟล์บนดิสก์ เครื่อง Java จะถามระบบปฏิบัติการเพื่อการเข้าถึงแบบเอกสิทธิ์เฉพาะบุคคล หากทรัพยากรนั้นว่าง เครื่อง Java จะได้รับ มัน.

"แต่หลังจากที่คุณทำงานกับไฟล์เสร็จแล้ว ทรัพยากร (ไฟล์) นี้จะต้องได้รับการปล่อยตัว กล่าวคือ คุณต้องแจ้งให้ระบบปฏิบัติการทราบว่าคุณไม่ต้องการอีกต่อไปหากคุณไม่ทำเช่นนี้ ทรัพยากรจะยังคงเป็น จัดโดยโปรแกรมของคุณ "

"นั่นฟังดูยุติธรรม"

"เพื่อให้เป็นเช่นนั้น ระบบปฏิบัติการจะรักษารายการของทรัพยากรที่ครอบครองโดยโปรแกรมที่กำลังรันอยู่ ถ้าโปรแกรมของคุณมีทรัพยากรเกินขีดจำกัดที่กำหนดไว้ ระบบปฏิบัติการจะไม่ให้ทรัพยากรใหม่แก่คุณอีกต่อไป

"มันเหมือนกับโปรแกรมที่สามารถกินหน่วยความจำทั้งหมด ... "

"อะไรทำนองนั้น ข่าวดีก็คือหากโปรแกรมของคุณยุติลง ทรัพยากรทั้งหมดจะถูกปล่อยโดยอัตโนมัติ (ระบบปฏิบัติการเองก็ทำเช่นนี้)"

“ถ้านั่นเป็นข่าวดี แสดงว่ามีข่าวร้ายหรือเปล่า”

"ใช่แล้ว ข่าวร้ายก็คือ หากคุณกำลังเขียนแอปพลิเคชันเซิร์ฟเวอร์..."

"แต่ฉันจะเขียนใบสมัครดังกล่าวหรือไม่"

"แอปพลิเคชันเซิร์ฟเวอร์จำนวนมากเขียนด้วยภาษาจาวา ดังนั้นเป็นไปได้มากว่าคุณจะเขียนแอปพลิเคชันเหล่านี้เพื่อการทำงาน อย่างที่ฉันพูด หากคุณกำลังเขียนแอปพลิเคชันเซิร์ฟเวอร์ เซิร์ฟเวอร์ของคุณจะต้องทำงานไม่หยุดเป็นเวลาหลายวัน สัปดาห์ เดือน ฯลฯ"

"กล่าวอีกนัยหนึ่งคือ โปรแกรมไม่ได้หยุดทำงาน และนั่นหมายความว่าหน่วยความจำจะไม่ถูกปล่อยออกมาโดยอัตโนมัติ"

"ถูกต้อง และถ้าคุณเปิดไฟล์ 100 ไฟล์ต่อวันและไม่ปิดมัน ในอีกไม่กี่สัปดาห์ แอปพลิเคชันของคุณจะถึงขีดจำกัดของทรัพยากรและหยุดทำงาน"

"งานที่มั่นคงเหลืออีกหลายเดือน! จะทำอะไรได้บ้าง"

"คลาสที่ใช้ทรัพยากรภายนอกมีวิธีพิเศษในการเผยแพร่: close().

"ต่อไปนี้เป็นตัวอย่างของโปรแกรมที่เขียนบางอย่างลงในไฟล์แล้วปิดไฟล์เมื่อทำงานเสร็จ นั่นคือทำให้ทรัพยากรของระบบปฏิบัติการว่างลง หน้าตาประมาณนี้:

รหัส บันทึก
String path = "c:\\projects\\log.txt";
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
เส้นทางไปยังไฟล์.
รับวัตถุไฟล์: รับทรัพยากร
เขียนลงไฟล์
ปิดไฟล์ - ปล่อยทรัพยากร

"อา... หลังจากทำงานกับไฟล์ (หรือทรัพยากรภายนอกอื่น ๆ) ฉันต้องเรียกใช้เมธอดclose()บนวัตถุที่เชื่อมโยงกับทรัพยากรภายนอก"

"ใช่ ทุกอย่างดูเหมือนง่าย แต่ข้อยกเว้นสามารถเกิดขึ้นได้เมื่อโปรแกรมทำงาน และทรัพยากรภายนอกจะไม่ถูกปล่อยออกมา"

“แล้วมันแย่มาก ทำไงดี”

"เพื่อให้แน่ใจว่าclose()มีการเรียกใช้เมธอดเสมอ เราจำเป็นต้องห่อโค้ดของเราใน บล็อก try- catch- finallyและเพิ่มclose()เมธอดลงในfinallyบล็อก ซึ่งจะมีลักษณะดังนี้:

try
{
   FileOutputStream output = new FileOutputStream(path);
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

"หืม... มีอะไรผิดปกติที่นี่?"

"ถูกต้อง โค้ดนี้จะไม่คอมไพล์ เนื่องจากoutputตัวแปรถูกประกาศภายในtry{}บล็อก ดังนั้นจึงมองไม่เห็นในfinallyบล็อก

มาแก้ไขกันเถอะ:

FileOutputStream output = new FileOutputStream(path);

try
{
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

“ตอนนี้ทุกอย่างโอเคไหม?”

"ไม่เป็นไร แต่จะไม่ทำงานหากมีข้อผิดพลาดเกิดขึ้นเมื่อเราสร้างวัตถุFileOutputStreamและสิ่งนี้อาจเกิดขึ้นได้ค่อนข้างง่าย

มาแก้ไขกันเถอะ:

FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

"และทุกอย่างทำงานตอนนี้หรือไม่"

"ยังมีข้อวิจารณ์อยู่บ้าง ประการแรก หากมีข้อผิดพลาดเกิดขึ้นเมื่อสร้างวัตถุFileOutputStreamตัวแปรนั้นoutputจะเป็นโมฆะ ความเป็นไปได้นี้จะต้องนำมาพิจารณาในfinallyบล็อก

" close()ประการที่สอง เมธอดจะถูกเรียกใช้ในfinallyบล็อกเสมอ ซึ่งหมายความว่าไม่จำเป็นในtryบล็อก รหัสสุดท้ายจะมีลักษณะดังนี้:

FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   if (output!=null)
      output.close();
}

"แม้ว่าเราจะไม่พิจารณาบล็อกcatchซึ่งสามารถละเว้นได้ ดังนั้นโค้ด 3 บรรทัดของเราจึงกลายเป็น 10 แต่โดยพื้นฐานแล้ว เราเพิ่งเปิดไฟล์และเขียน 1"

“ฟู่... เป็นเรื่องที่ดีที่สรุปเรื่องนี้ได้ ค่อนข้างเข้าใจ แต่ค่อนข้างน่าเบื่อใช่ไหม”

"เป็นเช่นนั้น นั่นเป็นเหตุผลที่ผู้สร้างของ Java ช่วยเราโดยการเพิ่มน้ำตาลเชิงประโยค ตอนนี้เรามาดูไฮไลท์ของโปรแกรมหรือมากกว่านั้นคือบทเรียนนี้:

try-พร้อมทรัพยากร

"เริ่มต้นด้วยเวอร์ชันที่ 7 Java มีtryคำสั่ง -with-resources ใหม่

"มันถูกสร้างขึ้นอย่างแม่นยำเพื่อแก้ปัญหาด้วยการเรียกเมธอดที่จำเป็นclose()"

"ฟังดูมีความหวัง!"

"กรณีทั่วไปดูค่อนข้างง่าย:

try (ClassName name = new ClassName())
{
   Code that works with the name variable
}

"นี่คือการเปลี่ยนแปลงของtry คำสั่ง อื่น ?"

"ใช่ คุณต้องเพิ่มวงเล็บหลังtryคำหลัก จากนั้นสร้างวัตถุที่มีทรัพยากรภายนอกอยู่ภายในวงเล็บ สำหรับแต่ละวัตถุในวงเล็บ คอมไพเลอร์จะเพิ่มส่วนfinallyและการเรียกใช้close()เมธอด

"ด้านล่างเป็นตัวอย่างที่เทียบเท่ากันสองตัวอย่าง:

รหัสยาว รหัสที่มีการลองด้วยทรัพยากร
FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
}
finally
{
   if (output!=null)
   output.close();
}
try(FileOutputStream output = new FileOutputStream(path))
{
   output.write(1);
}

"เจ๋งมาก! โค้ดที่ใช้try-with-resources นั้นสั้นกว่าและอ่านง่ายกว่ามาก ยิ่งเรามีโค้ดน้อย โอกาสพิมพ์ผิดหรือข้อผิดพลาดอื่นๆ ก็น้อยลง"

"ฉันดีใจที่คุณชอบ อย่างไรก็ตาม เราสามารถเพิ่มcatchและfinallyบล็อกtryคำสั่ง -with-resources ได้ หรือคุณไม่สามารถเพิ่มได้หากไม่จำเป็น

หลายตัวแปรในเวลาเดียวกัน

"คุณอาจพบกับสถานการณ์บ่อยครั้งเมื่อจำเป็นต้องเปิดไฟล์หลายไฟล์พร้อมกัน สมมติว่าคุณกำลังคัดลอกไฟล์ ดังนั้นคุณต้องมีวัตถุสองชิ้น: ไฟล์ที่คุณกำลังคัดลอกข้อมูลและไฟล์ที่คุณกำลังคัดลอกข้อมูล .

"ในกรณีนี้tryคำสั่ง -with-resources ให้คุณสร้างหนึ่งแต่หลายวัตถุในนั้น โค้ดที่สร้างวัตถุต้องคั่นด้วยเครื่องหมายอัฒภาค นี่คือลักษณะทั่วไปของคำสั่งนี้:

try (ClassName name = new ClassName(); ClassName2 name2 = new ClassName2())
{
   Code that works with the name and name2 variables
}

ตัวอย่างการคัดลอกไฟล์:

รหัสสั้น รหัสยาว
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);

FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = input.readAllBytes();
   output.write(buffer);
}
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

FileInputStream input = null;
FileOutputStream output = null;

try
{
   input = new FileInputStream(src);
   output = new FileOutputStream(dest);

   byte[] buffer = input.readAllBytes();
   output.write(buffer);
}
finally
{
   if (input!=null)
      input.close();
   if (output!=null)
      output.close();
}

"เราจะว่าอย่างไรดี - tryด้วยทรัพยากรเป็นสิ่งที่วิเศษมาก!"

"สิ่งที่เราสามารถพูดได้ว่าเราควรใช้มัน"

ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION