JavaRush /จาวาบล็อก /Random-TH /ระดับ 26 คำตอบสำหรับคำถามสัมภาษณ์ในหัวข้อระดับ ส่วนที่ 2 ...
zor07
ระดับ
Санкт-Петербург

ระดับ 26 คำตอบสำหรับคำถามสัมภาษณ์ในหัวข้อระดับ ส่วนที่ 2 คำถาม 6-9, 11-12

เผยแพร่ในกลุ่ม
ระดับ 26 คำตอบสำหรับคำถามสัมภาษณ์ในหัวข้อระดับ  ส่วนที่ 2 คำถาม 6-9, 11-12 - 1

6. แคนคาเรนซีคืออะไร?

Concurrencyเป็นไลบรารีคลาสใน Java ที่มีคลาสพิเศษที่ปรับให้เหมาะสมสำหรับการทำงานกับหลายเธรด java.util.concurrentคลาสเหล่า นี้ถูกรวบรวมไว้ในแพ็คเกจ สามารถแบ่งตามแผนผังตามฟังก์ชันการทำงานได้ดังนี้: ระดับ 26 คำตอบสำหรับคำถามสัมภาษณ์ในหัวข้อระดับ  ส่วนที่ 2 คำถาม 6-9, 11-12 - 2Concurrent Collections - ชุดคอลเลกชันที่ทำงานอย่างมีประสิทธิภาพในสภาพแวดล้อมแบบมัลติเธรดมากกว่าคอลเลกชันสากลมาตรฐานจากjava.utilแพ็คเกจ แทนที่จะใช้ wrapper พื้นฐานCollections.synchronizedListที่บล็อกการเข้าถึงคอลเลกชันทั้งหมด จะใช้การล็อกเซ็กเมนต์ข้อมูล หรืองานได้รับการปรับให้เหมาะสมสำหรับการอ่านข้อมูลแบบขนานโดยใช้อัลกอริธึมที่ไม่ต้องรอ Queues - การไม่บล็อกและการบล็อกคิวด้วยการสนับสนุนแบบมัลติเธรด คิวที่ไม่ปิดกั้นได้รับการออกแบบเพื่อความรวดเร็วและการทำงานโดยไม่ปิดกั้นเธรด คิวการบล็อกจะใช้เมื่อคุณต้องการ "ชะลอ" เธรด "ผู้ผลิต" หรือ "ผู้บริโภค" หากไม่ตรงตามเงื่อนไขบางประการ เช่น คิวว่างเปล่าหรือล้น หรือไม่มี "ผู้บริโภค" ที่ว่าง Synchronizersเป็นยูทิลิตี้เสริมสำหรับการซิงโครไนซ์เธรด พวกมันเป็นอาวุธอันทรงพลังในการประมวลผลแบบ "คู่ขนาน" ผู้ดำเนินการ - มีเฟรมเวิร์กที่ยอดเยี่ยมสำหรับการสร้างเธรดพูล การกำหนดเวลางานอะซิงโครนัส และการได้รับผลลัพธ์ การล็อค - แสดงถึงกลไกการซิงโครไนซ์ เธรดทางเลือกและมีความยืดหยุ่นมากกว่าเมื่อเปรียบเทียบกับ synchronizedกลไกwaitพื้นฐาน Atomics - คลาสที่รองรับการดำเนินการของอะตอมในแบบดั้งเดิมและการอ้างอิง แหล่งที่มา:notifynotifyAll

7.คุณรู้จักวิชาอะไรจากกันคะเรนสีบ้าง?

คำตอบสำหรับคำถามนี้ระบุไว้อย่างสมบูรณ์ในบทความนี้ ฉันไม่เห็นประเด็นที่จะต้องพิมพ์ซ้ำทั้งหมดที่นี่ ดังนั้น ฉันจะให้คำอธิบายเฉพาะชั้นเรียนที่ฉันได้รับเกียรติให้ทำความคุ้นเคยสั้นๆ เท่านั้น ConcurrentHashMap<K, V> - ต่างจากHashtableและบล็อกsynhronizedบนHashMapข้อมูลจะถูกนำเสนอในรูปแบบของเซ็กเมนต์ โดยแบ่งออกเป็นแฮชของคีย์ เป็นผลให้ข้อมูลถูกเข้าถึงโดยส่วนต่างๆ แทนที่จะเป็นวัตถุเดี่ยว นอกจากนี้ ตัววนซ้ำจะแสดงข้อมูลในช่วงระยะเวลาหนึ่งและไม่ต้องConcurrentModificationExceptionโยน AtomicBoolean, AtomicInteger, AtomicLong, AtomicIntegerArray, AtomicLongArray - จะเกิดอะไรขึ้นถ้าในคลาสที่คุณต้องการซิงโครไนซ์การเข้าถึงตัวแปรประเภทง่าย ๆ ตัวเดียวint? คุณสามารถใช้โครงสร้างด้วยsynchronizedและเมื่อใช้การดำเนินการแบบอะตอมมิset/getvolatileแต่คุณสามารถทำได้ดียิ่งขึ้นโดยใช้คลาสAtomic*ใหม่ เนื่องจากการใช้ CAS การดำเนินการกับคลาสเหล่านี้จึงเร็วกว่าการซิงโครไนซ์ผ่านsynchronized/volatile. นอกจากนี้ยังมีวิธีการบวกอะตอมมิกตามจำนวนที่กำหนด เช่นเดียวกับการเพิ่ม/ลด

8. คลาส ConcurrentHashMap ทำงานอย่างไร

เมื่อถึงเวลาเปิดตัวConcurrentHashMapนักพัฒนา Java จำเป็นต้องมีการใช้งานแผนที่แฮชต่อไปนี้:
  • ความปลอดภัยของด้าย
  • ไม่มีการล็อคทั้งโต๊ะขณะเข้าถึง
  • เป็นที่พึงประสงค์ว่าไม่มีการล็อกตารางเมื่อดำเนินการอ่าน
แนวคิดหลักในการดำเนินการConcurrentHashMapมีดังนี้:
  1. องค์ประกอบแผนที่

    ต่างจากองค์ประกอบHashMapin ถูกประกาศเป็นEntry. นี่เป็นคุณลักษณะที่สำคัญ เนื่องจากการเปลี่ยนแปลงในJMMConcurrentHashMapvolatile

    static final class HashEntry<K, V> {
        final K key;
        final int hash;
        volatile V value;
        final HashEntry<K, V> next;
    
        HashEntry(K key, int hash, HashEntry<K, V> next, V value) {
            this .key = key;
            this .hash = hash;
            this .next = next;
            this .value = value;
         }
    
        @SuppressWarnings("unchecked")
        static final <K, V> HashEntry<K, V>[] newArray(int i) {
            return new HashEntry[i];
        }
    }
  2. ฟังก์ชันแฮช

    ConcurrentHashMapนอกจากนี้ยังใช้ฟังก์ชันการแฮชที่ได้รับการปรับปรุงอีกด้วย

    ฉันขอเตือนคุณว่ามันเป็นอย่างไรในHashMapJDK 1.2:

    static int hash(int h) {
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    เวอร์ชันจาก ConcurrentHashMap JDK 1.5:

    private static int hash(int h) {
        h += (h << 15) ^ 0xffffcd7d;
        h ^= (h >>> 10);
        h += (h << 3);
        h ^= (h >>> 6);
        h += (h << 2) + (h << 14);
        return h ^ (h >>> 16);
    }

    เหตุใดจึงต้องทำให้ฟังก์ชันแฮชซับซ้อนยิ่งขึ้น ตารางในแฮชแมปมีความยาวที่กำหนดด้วยกำลังสอง สำหรับรหัสแฮชที่มีการแทนค่าไบนารี่ไม่แตกต่างกันในตำแหน่งต่ำและสูง เราจะเกิดการชนกัน การเพิ่มความซับซ้อนของฟังก์ชันแฮชเพียงช่วยแก้ปัญหานี้ โดยลดโอกาสที่จะเกิดการชนกันในแผนที่

  3. เซ็กเมนต์

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

  4. ระดับการทำงานพร้อมกัน

    พารามิเตอร์นี้ส่งผลต่อการใช้งานการ์ดหน่วยความจำและจำนวนเซ็กเมนต์ในการ์ด

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

  5. ทั้งหมด

    ดังนั้น ข้อดีหลักและคุณสมบัติการใช้งานConcurrentHashMap:

    • hashmapแผนที่มี ส่วนต่อประสานการโต้ตอบคล้ายกับ
    • การดำเนินการอ่านไม่จำเป็นต้องล็อกและดำเนินการแบบขนาน
    • การดำเนินการเขียนมักจะสามารถดำเนินการแบบขนานโดยไม่มีการปิดกั้น
    • เมื่อสร้าง จะต้องระบุสิ่งที่จำเป็นconcurrencyLevelกำหนดโดยการอ่านและการเขียนสถิติ
    • องค์ประกอบแผนที่มีค่าvalueประกาศเป็นvolatile
    ที่มา: ConcurrentHashMap ทำงานอย่างไร

9. คลาสล็อคคืออะไร?

เพื่อควบคุมการเข้าถึงทรัพยากรที่ใช้ร่วมกัน เราสามารถใช้การล็อคเป็นทางเลือกแทนตัวดำเนินการที่ซิงโครไนซ์ได้ ฟังก์ชั่นการล็อคบรรจุอยู่ในjava.util.concurrent.locks. ขั้นแรก เธรดพยายามเข้าถึงทรัพยากรที่ใช้ร่วมกัน หากว่างก็จะทำการล็อคบนด้าย เมื่องานเสร็จสิ้น การล็อกทรัพยากรที่ใช้ร่วมกันจะถูกปลดล็อก หากทรัพยากรไม่ว่างและมีการล็อคไว้แล้ว เธรดจะรอจนกว่าการล็อคนี้จะถูกปลดล็อค คลาสล็อคใช้อินเทอร์เฟซLockที่กำหนดวิธีการต่อไปนี้:
  • void lock():รอจนกว่าจะได้รับล็อค
  • boolean tryLock():พยายามรับการล็อค หากได้รับการล็อค มันจะคืนค่าtrue หากไม่ได้รับล็อค ก็จะส่งกลับfalse ต่างจากวิธีการนี้ตรงที่lock()จะไม่รอที่จะได้รับการล็อคหากไม่มีการล็อค
  • void unlock():ถอดล็อคออก
  • Condition newCondition():ส่งคืนวัตถุConditionที่เกี่ยวข้องกับการล็อคปัจจุบัน
องค์กรของการล็อคในกรณีทั่วไปนั้นค่อนข้างง่าย: เพื่อให้ได้การล็อควิธีการจะถูกเรียกว่าlock()และหลังจากเสร็จสิ้นการทำงานกับทรัพยากรที่ใช้ร่วมกัน วิธีการนั้นจะถูกเรียกว่าunlock()ซึ่งจะปล่อยการล็อค วัตถุConditionช่วยให้คุณจัดการการบล็อกได้ ตามกฎแล้วในการทำงานกับการล็อคจะใช้คลาสReentrantLockจากแพ็คเกจjava.util.concurrent.locks.คลาสนี้ใช้อินเทอร์เฟLockซ มาดูการใช้ Java Lock API โดยใช้โปรแกรมขนาดเล็กเป็นตัวอย่าง: สมมติว่าเรามีคลาสที่มีResourceเมธอดเธรดที่ปลอดภัยสองสามวิธี และเมธอดที่ไม่จำเป็นต้องมีความปลอดภัยของเธรด
public class Resource {

    public void doSomething(){
        // пусть здесь происходит работа с базой данных
    }

    public void doLogging(){
        // потокобезопасность для логгирования нам не требуется
    }
}
ตอนนี้เรามาดูคลาสที่ใช้อินเทอร์เฟซRunnableและใช้วิธีการเรียนResourceกัน
public class SynchronizedLockExample implements Runnable{

    // экземпляр класса Resource для работы с методами
    private Resource resource;

    public SynchronizedLockExample(Resource r){
        this.resource = r;
    }

    @Override
    public void run() {
        synchronized (resource) {
            resource.doSomething();
        }
        resource.doLogging();
    }
}
ตอนนี้เรามาเขียนโปรแกรมด้านบนใหม่โดยใช้ Lock API แทนsynchronized.
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// класс для работы с Lock API. Переписан с приведенной выше программы,
// но уже без использования ключевого слова synchronized
public class ConcurrencyLockExample implements Runnable{

    private Resource resource;
    private Lock lock;

    public ConcurrencyLockExample(Resource r){
        this.resource = r;
        this.lock = new ReentrantLock();
    }

    @Override
    public void run() {
        try {
            // лочим на 10 секунд
            if(lock.tryLock(10, TimeUnit.SECONDS)){
            resource.doSomething();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            //убираем лок
            lock.unlock();
        }
        // Для логгирования не требуется потокобезопасность
        resource.doLogging();
    }

}
ดังที่คุณเห็นจากโปรแกรม เราใช้วิธีนี้tryLock()เพื่อให้แน่ใจว่าเธรดจะรอเพียงระยะเวลาหนึ่งเท่านั้น หากไม่ได้รับการล็อคบนอ็อบเจ็กต์ มันก็จะบันทึกและออก อีกประเด็นสำคัญ คุณต้องใช้บล็อกtry-finallyเพื่อให้แน่ใจว่าการล็อคจะถูกปล่อยแม้ว่าเมธอดdoSomething()จะส่งข้อยกเว้น ก็ตาม แหล่งที่มา:

11. มิวเท็กซ์คืออะไร?

mutexเป็นอ็อบเจ็กต์พิเศษสำหรับการซิงโครไนซ์เธรด/กระบวนการ อาจใช้เวลาสองรัฐ - ไม่ว่างและฟรี เพื่อให้ง่ายขึ้น mutex คือตัวแปรบูลีนที่รับค่าสองค่า: ไม่ว่าง (จริง) และว่าง (เท็จ) เมื่อเธรดต้องการความเป็นเจ้าของแต่เพียงผู้เดียวของอ็อบเจ็กต์ เธรดจะทำเครื่องหมาย mutex ว่าไม่ว่าง และเมื่อเธรดทำงานกับเธรดนั้นเสร็จสิ้น จะทำเครื่องหมาย mutex ว่าว่าง mutex ถูกแนบไปกับทุกอ็อบเจ็กต์ใน Java เฉพาะเครื่อง Java เท่านั้นที่สามารถเข้าถึง mutex ได้โดยตรง มันถูกซ่อนจากโปรแกรมเมอร์

12. จอภาพคืออะไร?

จอภาพเป็นกลไกพิเศษ (โค้ดชิ้นหนึ่ง) ซึ่งเป็นส่วนเสริมบน mutex ซึ่งช่วยให้มั่นใจได้ถึงการทำงานที่ถูกต้อง ท้ายที่สุดแล้ว การทำเครื่องหมายว่าอ็อบเจ็กต์ไม่ว่างนั้นไม่เพียงพอ เราต้องตรวจสอบให้แน่ใจด้วยว่าเธรดอื่นไม่พยายามใช้อ็อบเจ็กต์ไม่ว่าง ใน Java มอนิเตอร์ถูกใช้งานโดยใช้synchronizedคีย์เวิร์ด เมื่อเราเขียนบล็อกที่ซิงโครไนซ์ คอมไพลเลอร์ Java จะแทนที่ด้วยโค้ดสามชิ้น:
  1. ที่จุดเริ่มต้นของบล็อกsynchronizedโค้ดจะถูกเพิ่มเพื่อทำเครื่องหมาย mutex ว่าไม่ว่าง
  2. ที่ส่วนท้ายของบล็อกsynchronizedจะมีการเพิ่มโค้ดที่ทำเครื่องหมาย mutex ว่าว่าง
  3. ก่อนบล็อกsynchronizedจะมีการเพิ่มโค้ดเพื่อตรวจสอบว่า mutex ไม่ว่างหรือไม่ จากนั้นเธรดต้องรอให้รีลีส
ส่วนที่ 1
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION