JavaRush /Java Blog /Random-TL /Antas 26. Mga sagot sa mga tanong sa panayam sa antas ng ...
zor07
Antas
Санкт-Петербург

Antas 26. Mga sagot sa mga tanong sa panayam sa antas ng paksa. Bahagi 2. Mga Tanong 6-9, 11-12

Nai-publish sa grupo
Antas 26. Mga sagot sa mga tanong sa panayam sa antas ng paksa.  Bahagi 2. Mga Tanong 6-9, 11-12 - 1

6. Ano ang Cancarenzi?

Ang Concurrency ay isang library ng klase sa Java na naglalaman ng mga espesyal na klase na na-optimize para sa pagtatrabaho sa maraming thread. Ang mga klase na ito ay kinokolekta sa isang pakete java.util.concurrent. Maaari silang hatiin ayon sa eskematiko ayon sa functionality tulad ng sumusunod: Antas 26. Mga sagot sa mga tanong sa panayam sa antas ng paksa.  Bahagi 2. Mga Tanong 6-9, 11-12 - 2Concurrent Collections - isang set ng mga koleksyon na mas mahusay na gumagana sa isang multi-threaded na kapaligiran kaysa sa karaniwang mga unibersal na koleksyon mula java.utilsa package. Sa halip na isang pangunahing wrapper Collections.synchronizedListna may pagharang sa access sa buong koleksyon, ginagamit ang mga lock sa mga segment ng data, o ang trabaho ay na-optimize para sa parallel na pagbabasa ng data gamit ang mga algorithm na walang paghihintay. Mga Queue - hindi humaharang at humaharang sa mga pila na may suporta sa multi-threading. Ang mga hindi nakaharang na pila ay idinisenyo para sa bilis at operasyon nang hindi hinaharangan ang mga thread. Ginagamit ang pagharang sa mga pila kapag kailangan mong "pabagalin" ang mga thread na "Producer" o "Consumer" kung ang ilang kundisyon ay hindi natutugunan, halimbawa, ang pila ay walang laman o umaapaw, o walang libreng "Consumer". Ang mga synchronizer ay mga auxiliary utilities para sa pag-synchronize ng mga thread. Ang mga ito ay isang makapangyarihang sandata sa "parallel" computing. Executors - naglalaman ng mahuhusay na frameworks para sa paglikha ng mga thread pool, pag-iskedyul ng mga asynchronous na gawain at pagkuha ng mga resulta. Locks - kumakatawan sa mga alternatibo at mas nababaluktot na mekanismo ng pag-synchronize ng thread kumpara sa synchronizedmga waitpangunahing notify. Atomics - mga klase na may suporta para sa atomic operations sa primitives at reference. Pinagmulan:notifyAll

7. Anong mga klase mula sa Kankarensi ang alam mo?

Ang sagot sa tanong na ito ay ganap na nakasaad sa artikulong ito . Hindi ko nakikita ang punto sa muling pag-print ng lahat dito, kaya magbibigay lang ako ng mga paglalarawan sa mga klase na nagkaroon ako ng karangalan na madaling pamilyar sa aking sarili. ConcurrentHashMap<K, V> - Hindi tulad Hashtableat hinaharangan synhronizedsa HashMap, ang data ay ipinakita sa anyo ng mga segment, na nahahati sa mga hash ng mga key. Bilang resulta, ang data ay ina-access ng mga segment sa halip na sa pamamagitan ng isang bagay. Bilang karagdagan, ang mga iterator ay kumakatawan sa data para sa isang tiyak na tagal ng panahon at hindi nagtatapon ng ConcurrentModificationException. AtomicBoolean, AtomicInteger, AtomicLong, AtomicIntegerArray, AtomicLongArray - Paano kung sa isang klase kailangan mong i-synchronize ang access sa isang simpleng variable ng uri int? Maaari kang gumamit ng mga construct na may synchronized, at kapag gumagamit ng atomic operations set/get, volatile. Ngunit maaari kang gumawa ng mas mahusay sa pamamagitan ng paggamit ng mga bagong klase Atomic*. Dahil sa paggamit ng CAS, ang mga pagpapatakbo sa mga klase na ito ay mas mabilis kaysa sa pag-synchronize sa pamamagitan ng synchronized/volatile. Dagdag pa, may mga pamamaraan para sa atomic na pagdaragdag sa pamamagitan ng isang naibigay na halaga, pati na rin ang pagtaas/pagbawas.

8. Paano gumagana ang klase ng ConcurrentHashMap?

Sa oras ng pagpapakilala nito, ConcurrentHashMapkailangan ng mga developer ng Java ang sumusunod na pagpapatupad ng hash map:
  • Kaligtasan ng thread
  • Walang mga kandado sa buong mesa habang ina-access ito
  • Ito ay kanais-nais na walang mga kandado ng talahanayan kapag nagsasagawa ng isang read operation
Ang mga pangunahing ideya sa pagpapatupad ConcurrentHashMapay ang mga sumusunod:
  1. Mga elemento ng mapa

    Hindi tulad ng mga elemento HashMap, Entryin ConcurrentHashMapay ipinahayag bilang volatile. Isa itong mahalagang feature, dahil din sa mga pagbabago sa JMM .

    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. Pag-andar ng hash

    ConcurrentHashMapginagamit din ang isang pinahusay na pag-andar ng hashing.

    Hayaan mong ipaalala ko sa iyo kung ano ito sa HashMapJDK 1.2:

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

    Bersyon mula sa 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);
    }

    Bakit kailangang gawing mas kumplikado ang hash function? Ang mga talahanayan sa isang hash na mapa ay may haba na tinutukoy ng kapangyarihan ng dalawa. Para sa mga hash code na ang mga binary na representasyon ay hindi naiiba sa mababa at mataas na posisyon, magkakaroon tayo ng mga banggaan. Ang pagpapataas ng pagiging kumplikado ng hash function ay malulutas lamang ang problemang ito, na binabawasan ang posibilidad ng mga banggaan sa mapa.

  3. Mga segment

    Ang mapa ay nahahati sa N iba't ibang mga segment (16 bilang default, ang maximum na halaga ay maaaring 16 bits at isang kapangyarihan ng dalawa). Ang bawat segment ay isang thread-safe na talahanayan ng mga elemento ng mapa. Ang pagpapataas ng bilang ng mga segment ay hihikayat sa mga pagpapatakbo ng pagbabago na sumasaklaw sa maramihang mga segment, na binabawasan ang posibilidad ng pagharang sa runtime.

  4. ConcurrencyLevel

    Ang parameter na ito ay nakakaapekto sa paggamit ng memory card at ang bilang ng mga segment sa card.

    Ang bilang ng mga segment ay pipiliin bilang ang pinakamalapit na kapangyarihan ng dalawang mas mataas sa concurrencyLevel. Ang pagpapababa sa concurrencyLevel ay ginagawang mas malamang na ang mga thread ay haharangin ang mga segment ng mapa kapag nagsusulat. Ang labis na pagpapahalaga sa tagapagpahiwatig ay humahantong sa hindi mahusay na paggamit ng memorya. Kung isang thread lang ang magbabago sa mapa, at magbabasa ang iba, inirerekomendang gamitin ang value 1.

  5. Kabuuan

    Kaya, ang mga pangunahing bentahe at mga tampok ng pagpapatupad ConcurrentHashMap:

    • hashmapAng mapa ay may interface ng pakikipag-ugnayan na katulad ng
    • Ang mga operasyon sa pagbabasa ay hindi nangangailangan ng mga kandado at isinasagawa nang magkatulad
    • Ang mga pagpapatakbo ng pagsulat ay madalas ding maisagawa nang magkatulad nang walang pagharang
    • Kapag lumilikha, ang kinakailangan ay ipinahiwatig concurrencyLevel, na tinutukoy sa pamamagitan ng pagbabasa at pagsulat ng mga istatistika
    • Ang mga elemento ng mapa ay may halagang valueidineklara bilangvolatile
    Pinagmulan: Paano Gumagana ang ConcurrentHashMap

9. Ano ang klase ng Lock?

Upang kontrolin ang pag-access sa isang nakabahaging mapagkukunan, maaari naming gamitin ang mga kandado bilang alternatibo sa naka-synchronize na operator. Naka-package ang locking functionality sa java.util.concurrent.locks. Una, sinusubukan ng thread na i-access ang nakabahaging mapagkukunan. Kung ito ay libre, pagkatapos ay isang lock ang inilalagay sa thread. Kapag nakumpleto na ang gawain, ilalabas ang lock sa nakabahaging mapagkukunan. Kung ang mapagkukunan ay hindi libre at may nakalagay na lock dito, maghihintay ang thread hanggang sa maalis ang lock na ito. Ang mga klase ng lock ay nagpapatupad ng isang interface Lockna tumutukoy sa mga sumusunod na pamamaraan:
  • void lock():naghihintay hanggang sa makuha ang lock
  • boolean tryLock():sumusubok na kumuha ng lock; kung makuha ang lock, babalik ito ng totoo . Kung ang lock ay hindi nakuha, ito ay nagbabalik ng false . Hindi tulad ng pamamaraan, lock()hindi ito naghihintay na makakuha ng isang lock kung ang isa ay hindi magagamit
  • void unlock():tinatanggal ang lock
  • Condition newCondition():ibinabalik ang bagay Conditionna nauugnay sa kasalukuyang lock
Ang organisasyon ng pag-lock sa pangkalahatang kaso ay medyo simple: upang makuha ang lock, ang pamamaraan ay tinatawag na lock(), at pagkatapos ng pagtatapos ng pagtatrabaho sa mga nakabahaging mapagkukunan, ang pamamaraan ay tinatawag na unlock(), na naglalabas ng lock. Ang bagay ay Conditionnagpapahintulot sa iyo na pamahalaan ang pagharang. Bilang isang patakaran, upang gumana sa mga lock, isang klase ReentrantLockmula sa package ang ginagamit. java.util.concurrent.locks.Ang klase na ito ay nagpapatupad ng interface Lock. Tingnan natin ang paggamit ng Java Lock API gamit ang isang maliit na programa bilang isang halimbawa: Kaya, sabihin nating mayroon tayong klase Resourcena may ilang pamamaraan at pamamaraan na ligtas sa thread kung saan hindi kinakailangan ang kaligtasan ng thread.
public class Resource {

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

    public void doLogging(){
        // потокобезопасность для логгирования нам не требуется
    }
}
Ngayon ay kumuha tayo ng isang klase na nagpapatupad ng interface Runnableat gumagamit ng mga pamamaraan ng klase 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();
    }
}
Ngayon ay muling isulat natin ang programa sa itaas gamit ang Lock API sa halip na ang 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();
    }

}
Tulad ng nakikita mo mula sa programa, ginagamit namin ang pamamaraan tryLock()upang matiyak na ang thread ay naghihintay lamang para sa isang tiyak na tagal ng oras. Kung hindi ito makakuha ng isang lock sa bagay, ito ay mag-log at lalabas lamang. Isa pang mahalagang punto. Dapat kang gumamit ng isang bloke try-finallyupang matiyak na ang lock ay ilalabas kahit na ang pamamaraan doSomething()ay naghagis ng isang pagbubukod. Mga Pinagmulan:

11. Ano ang mutex?

Ang mutex ay isang espesyal na bagay para sa pag-synchronize ng mga thread/proseso. Maaaring tumagal ng dalawang estado - abala at libre. Upang pasimplehin, ang mutex ay isang boolean variable na kumukuha ng dalawang value: busy (true) at libre (false). Kapag nais ng isang thread ang eksklusibong pagmamay-ari ng isang bagay, minarkahan nito ang mutex nito bilang abala, at kapag natapos na itong magtrabaho dito, minarkahan nito ang mutex nito bilang libre. Ang isang mutex ay naka-attach sa bawat bagay sa Java. Ang Java machine lang ang may direktang access sa mutex. Ito ay nakatago mula sa programmer.

12. Ano ang monitor?

Ang monitor ay isang espesyal na mekanismo (isang piraso ng code) - isang add-on sa mutex, na nagsisiguro ng tamang operasyon dito. Pagkatapos ng lahat, hindi sapat na markahan na ang bagay ay abala; dapat din nating tiyakin na ang ibang mga thread ay hindi subukang gamitin ang abalang bagay. Sa Java, ang monitor ay ipinatupad gamit ang keyword synchronized. Kapag sumulat kami ng isang naka-synchronize na bloke, pinapalitan ito ng Java compiler ng tatlong piraso ng code:
  1. Sa simula ng block synchronized, idinaragdag ang code na nagmamarka sa mutex bilang abala.
  2. Sa dulo ng block, synchronizedmay idinagdag na code na nagmamarka sa mutex bilang libre.
  3. Bago ang block, synchronizedidinagdag ang code na sumusuri kung abala ang mutex, pagkatapos ay dapat hintayin ng thread na mailabas ito.
Bahagi 1
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION