JavaRush /จาวาบล็อก /Random-TH /คอฟฟี่เบรค #165. แพ็คเกจในภาษาจาวา วิธีที่ปลอดภัยสำหรับผู...

คอฟฟี่เบรค #165. แพ็คเกจในภาษาจาวา วิธีที่ปลอดภัยสำหรับผู้เริ่มต้น

เผยแพร่ในกลุ่ม

แพ็คเกจจาวา

ที่มา: Usemynotes โพสต์นี้จะช่วยให้คุณเข้าใจแพ็คเกจใน Java ได้ดีขึ้น เข้าใจวัตถุประสงค์และวิธีนำไปใช้ คอฟฟี่เบรค #165.  แพ็คเกจในภาษาจาวา  วิธีการใช้เธรดที่ปลอดภัยสำหรับผู้เริ่มต้น - 1

แพ็คเกจใน Java คืออะไร

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

แพ็คเกจบางประเภทใน Java:

  • java.lang - มาพร้อมกับ Java เป็นค่าเริ่มต้น
  • java.io - ประกอบด้วยคลาส วิธีการ และองค์ประกอบอื่นๆ ที่เกี่ยวข้องกับอินพุต/เอาท์พุต

เหตุใดจึงต้องมีแพ็คเกจ?

  • เพื่อหลีกเลี่ยงความขัดแย้งเรื่องชื่อ
  • เพื่อให้มีการควบคุมการเข้าถึง
  • เพื่อให้เกิดการห่อหุ้มข้อมูล

จะสร้างแพ็คเกจใน Java ได้อย่างไร?

มาสร้างแพ็คเกจที่เรียกว่าคอมพิวเตอร์กัน โดยทั่วไปชื่อแพ็คเกจจะเขียนด้วยตัวอักษรพิมพ์เล็ก ทำเช่นนี้เพื่อหลีกเลี่ยงความขัดแย้งของชื่อกับชื่อคลาสเท่านั้น เราจะสร้างอินเทอร์เฟซที่เรียกว่าPluggable ซึ่งจะอยู่ใน แพ็คเกจ คอมพิวเตอร์
package computer;

interface Pluggable {
   public void pluggedIn();
   public void pluggedOut();
}
ตอนนี้เราจะสร้างคลาสที่เรียกว่าPenDriveซึ่งจะใช้อินเทอร์เฟซข้างต้น
package computer;

public class PenDrive implements Pluggable {

   int storage = 64;

   public void pluggedIn () {
     System.out.println("Pen Drive is connected");
   }

   public void pluggedOut () {
     System.out.println("Pen Drive is removed");
   }

   public int storage() {
     return storage;
   }

   public static void main(String args[]) {
     PenDrive p = new PenDrive ();
     p.pluggedIn();
     System.out.println("Pen Drive Storage: " + p.storage());
     p.pluggedOut();
   }
}

จะสร้างลำดับชั้นแพ็คเกจใน Java ได้อย่างไร?

เมื่อสร้างลำดับชั้น แพ็กเกจใน Java จะถูกตั้งชื่อในลำดับย้อนกลับ ทำให้คล้ายกับไดเร็กทอรีหรือโฟลเดอร์มาก เช่นเดียวกับบนคอมพิวเตอร์ส่วนบุคคล โดยที่โฟลเดอร์หนึ่งสามารถมีโฟลเดอร์ย่อยได้ตั้งแต่หนึ่งโฟลเดอร์ขึ้นไป แพ็คเกจใน Java ก็เช่นเดียวกัน มาดูแพ็คเกจที่ชื่อAsia.India.Kolkataกัน โฟลเดอร์เหล่านี้คือโฟลเดอร์ที่มีอยู่ทั้งหมด แต่หากคุณพิจารณาตามภูมิศาสตร์ จะเห็นได้ชัดว่ากัลกัตตาอยู่ในอินเดีย และอินเดียอยู่ในเอเชีย วัตถุประสงค์หลักของลำดับชั้นคือเพื่อให้ค้นหาคลาสได้ง่ายขึ้น

ประเภทของแพ็คเกจในภาษา Java

แพ็คเกจในตัว

แพ็คเกจบิวท์อินคือแพ็คเกจที่ประกอบด้วยคลาสบิวท์อินจำนวนมากที่เป็นส่วนหนึ่งของ Java API แพ็คเกจเหล่านี้ประกอบด้วย:
  • java.util - แพ็คเกจนี้มีจำนวนคลาสยูทิลิตี้ที่จำกัดซึ่งใช้ในการปรับใช้โครงสร้างข้อมูล เช่น รายการที่เชื่อมโยง ชุด และอื่นๆ นอกจากนี้ยังรองรับการทำงานวันที่และเวลาและอื่นๆ อีกมากมาย
  • java.net - ประกอบด้วยคลาสที่ใช้สำหรับการทำงานของเครือข่าย

แพ็คเกจที่ผู้ใช้กำหนด

แพ็คเกจที่กำหนดโดยผู้ใช้เรียกว่าแพ็คเกจผู้ใช้ ผู้ใช้สามารถสร้างแพ็คเกจด้วยตนเองและมีคลาสได้มากเท่าที่ต้องการ

จะเข้าถึงแพ็คเกจจากแพ็คเกจอื่นได้อย่างไร?

คุณสามารถเข้าถึงแพ็คเกจจากแพ็คเกจอื่นได้สามวิธีง่ายๆ:
  • การใช้เครื่องหมายดอกจันในคำสั่งนำเข้า
เครื่องหมาย ดอกจัน ( * ) ใช้เพื่อแสดงถึง “ทุกสิ่ง” ในภาษา Java เมื่อใช้มัน เราสามารถนำเข้าทุกอย่างที่อยู่ภายในแพ็คเกจย่อยของแพ็คเกจได้ ตัวอย่าง: พิจารณาแพ็คเกจชื่อtools หากเราต้องการนำเข้าทุกอย่างที่อยู่ในแพ็คเกจนี้ เราจำเป็นต้องใช้คำสั่งนำเข้าเช่น:
import tools.*;
  • ใช้การนำเข้าpackage.ClassName;
การกล่าวถึงชื่อคลาสในแพ็คเกจเป็นวิธีที่มีประสิทธิภาพในการนำเข้าเฉพาะคลาสที่คุณต้องการลงในโปรแกรมของคุณ ซึ่งจะช่วยหลีกเลี่ยงการนำเข้าคลาสที่ไม่จำเป็น ตัวอย่าง: พิจารณาแพ็คเกจชื่อbooks หากเราต้องการนำเข้าคลาสหรืออินเทอร์เฟซเฉพาะจากนั้น (เราจะดูที่ คลาส Pages ) เราก็สามารถนำเข้าได้โดยใช้:
import book.Pages;
  • โดยใช้ชื่อเต็มของคุณ
มีวิธีใช้แพ็กเกจ Java หรือคลาสโดยตรงโดยใช้ชื่อแบบเต็ม ด้วยวิธีนี้คุณไม่จำเป็นต้องนำเข้าแพ็คเกจและสามารถใช้งานได้โดยตรงในโปรแกรม ตัวอย่าง:
java.awt.List aSimpleList = new java.awt.List();

ขนาดแบตช์เริ่มต้นใน Java

ตามค่าเริ่มต้น Java จะนำเข้าแพ็คเกจjava.lang มีหลายคลาสที่ใช้กันทั่วไปในโปรแกรม Java ธรรมดา เช่นString , Integerและอื่นๆ หนึ่งในคลาสที่สำคัญที่สุดคือ คลาส Objectซึ่งจะพบได้ใน แพ็คเกจ java.lang เช่น กัน ขนาดของแพ็คเกจนี้ขึ้นอยู่กับส่วนประกอบ: 8 อินเทอร์เฟซ, 37 คลาส, 3 enums, 27 ข้อยกเว้น, 23 ประเภทข้อผิดพลาด และ 5 ประเภทคำอธิบายประกอบ

วิธี Java ที่ปลอดภัยสำหรับเธรดสำหรับผู้เริ่มต้น

ที่มา: ปานกลาง จากการใช้บทความนี้ คุณสามารถเรียนรู้เกี่ยวกับการทำงานของวิธี thread safe ใน Java คอฟฟี่เบรค #165.  แพ็คเกจในภาษาจาวา  วิธีที่ปลอดภัยสำหรับผู้เริ่มต้น - 2ฉันพบว่านักพัฒนา Java รุ่นเยาว์/กลางจำนวนมากเข้าใจผิดว่าวิธีการรักษาความปลอดภัยของเธรดควรทำงานอย่างไรในโครงการจริง และเนื่องจากปกติแล้วเราทำงานในสภาพแวดล้อมแบบมัลติเธรด การใช้อย่างถูกต้องจึงมีความสำคัญมาก วิธีการที่ปลอดภัยสำหรับเธรดเป็นวิธีการที่สามารถเรียกจากหลายเธรดพร้อมกันได้ โดยไม่ส่งผลกระทบต่อสถานะข้อมูลของกันและกัน ความเข้าใจแนวคิดนี้ไม่เพียงพอทำให้เกิดจุดบกพร่องที่ยากต่อการค้นหาและแก้ไข เพื่อหลีกเลี่ยงข้อผิดพลาด มาดูตัวอย่างกัน

ตัวอย่าง #1:

public static int countLetters(String input) {
    int counter = 0;

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            counter++;
        }
    }

    return counter;
}
  • เมธอดcountLettersเป็นแบบคงที่ โดยจะส่งกลับ ค่า intและยอมรับพารามิเตอร์สตริงเป็นอินพุต
  • ตัวนับตัวแปรดั้งเดิมจะถูกสร้างขึ้นภายในเมธอด จากนั้นวนซ้ำผ่านอักขระของสตริงอินพุตและเพิ่มตัวนับตัวแปรทุกครั้งที่พบอักขระตัวอักษร
เธรดวิธีนี้ปลอดภัยหรือไม่ นักพัฒนาหลายคนปฏิเสธ เพราะในกรณีนี้ เรามีการดำเนินการที่เพิ่มขึ้นซึ่งไม่ปลอดภัยสำหรับเธรด ลองคิดดูสิ ในโมเดลหน่วยความจำ Java เรามีสแต็กและฮีป แต่ละเธรดมีสแต็กของตัวเอง และเธรดทั้งหมดใช้ฮีปเดียวกัน ในเรื่องนี้ ข้อมูลสแต็กจะปลอดภัยสำหรับเธรดเสมอ แต่ข้อมูลฮีปไม่ปลอดภัย สแต็กเก็บการอ้างอิงดั้งเดิมและวัตถุ ฮีปประกอบด้วยอ็อบเจ็กต์เอง ซึ่งหมายความว่าในตัวอย่างโค้ดนี้ แต่ละเธรดจะเก็บตัว นับตัวแปร ของตัวเองไว้บนสแต็ก และไม่มีผลกระทบใด ๆ ต่อข้อมูลของเธรดอื่น ดังนั้นวิธีการนี้จึงปลอดภัยสำหรับเธรด โปรดทราบว่า ค่า String อินพุต ก็เป็นอ็อบเจ็กต์เช่นกัน แต่Stringและ wrappers ดั้งเดิม ( Integer , Long , Double , Booleanและอื่นๆ) ปลอดภัยสำหรับเธรดเนื่องจากไม่เปลี่ยนรูป

ตัวอย่าง #2:

public static int countLetters2(String input) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
รหัสนี้ใช้ตรรกะเดียวกันกับตัวอย่างแรก แต่ใช้ วัตถุ รายการ แทนตัวแปร intดั้งเดิม จากส่วนที่แล้ว เรารู้ว่าอ็อบเจ็กต์ใน Java ถูกเก็บไว้ในฮีป และรายการก็คืออ็อบเจ็กต์ เรายังรู้ด้วยว่าสแต็กเก็บการอ้างอิงถึงออบเจ็กต์บนฮีป ในตัวอย่าง #2 แต่ละเธรดจะสร้าง อ็อบเจ็กต์ ArrayList ใหม่ : และ ตัวแปร listCounterจะเก็บการอ้างอิงไปยังอ็อบเจ็กต์ของมันบนฮีป ดังนั้นจึงไม่มีเธรดอื่นใดที่สามารถเปลี่ยนอ็อบเจ็กต์นั้นได้
List<Character> listCounter = new ArrayList<>();
ซึ่งหมายความว่าวิธีนี้ปลอดภัยสำหรับเธรด

ตัวอย่าง #3:

public class CounterUtil { // singleton

    List<Character> listCounter = new ArrayList<>();

    public int countLetters3(String input) {
        for (Character c : input.toCharArray()) {
            if (Character.isAlphabetic(c)) {
                listCounter.add(c);
            }
        }

        return listCounter.size();
    }
}
ในตัวอย่างนี้ เรามี CounterUtil คลาสซิงเกิลตัน (ซึ่งเป็นสิ่งสำคัญ) พร้อมด้วยตัวแปรโกลบอลlistCounter ตัวแปรนี้ถูกสร้างขึ้นพร้อมกับอินสแตนซ์ซิงเกิลตัน เมื่อหลายเธรดเรียกใช้เมธอดcountChars3 เธรด ทั้งหมดจะใช้ตัวแปรโกลบอลlistCounter เดียวกัน ซึ่งจัดเก็บการอ้างอิงไปยังออบเจ็กต์เดียวกันบนฮีป และเธรดในนั้นจะมีอิทธิพลซึ่งกันและกัน ดังนั้นเราจึงสรุปได้ว่าวิธีนี้ไม่ปลอดภัยสำหรับเธรด และแม้ว่าเราจะเปลี่ยนList<Character> listCounterเป็นตัวแปรดั้งเดิมint counterมันก็จะไม่ปลอดภัยสำหรับเธรดเช่นกัน เนื่องจากเธรดทั้งหมดจะใช้ตัวแปรดั้งเดิมตัวเดียวกัน

ตัวอย่างสุดท้าย:

public static int countLetters4(List<Character> inputList) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : inputList) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
เมธอดcountLetters4ยอมรับรายการอักขระแทนพารามิเตอร์String ที่นี่เราไม่สามารถรับประกันได้ว่าวิธีนี้ปลอดภัยสำหรับเธรด ทำไม เพราะเราไม่แน่ใจว่านักพัฒนาจะใช้วิธีนี้อย่างไร หากเธรดอื่นจากภายนอกเปลี่ยนข้อมูลในinputListพร้อมกับ เมธอด counterLetters4 ของเรา อาจส่งผลต่อผลลัพธ์สุดท้าย

บทสรุป

เราได้ดูตัวอย่างเพียงสี่ตัวอย่างเท่านั้น และไม่ครอบคลุมทุกแง่มุมของความปลอดภัยของเธรดในโปรเจ็กต์ Java แต่เป็นจุดเริ่มต้นที่ดี ครั้งต่อไปที่คุณเห็นวิธีการในโค้ดของคุณ ให้ถามตัวเองว่า “เธรดวิธีนี้ปลอดภัยหรือไม่” และอีกไม่นานคุณก็จะเข้าใจคำตอบได้ชัดเจน
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION