JavaRush /Java блогы /Random-KK /Java тіліндегі SynchronousQueue мысалы - өндіруші тұтынуш...
profeg
Деңгей

Java тіліндегі SynchronousQueue мысалы - өндіруші тұтынушы мәселесін шешу

Топта жарияланған
Java тіліндегі SynchronousQueue мысалы - өндіруші тұтынушы мәселесін шешу
SynchronousQueue - әрбір кірістіру әрекеті басқа ағында сәйкес жою пәрменін күту керек және керісінше BlockingQueue арнайы түрі. SynchronousQueue жүйесінде put() әдісін шақырған кезде , ол басқа ағын осы элементті одан алғанша блоктайды. Сәйкесінше, егер басқа ағын одан элементті алып тастауға әрекеттенсе және элемент жоқ болса, онда бұл ағын басқа ағын элементті кезекке қойғанша блоктайды . SynchronousQueue-ді Олимпиада алауымен жүгіретін спортшы ( жіп ) деп ойлауға болады , ол алаумен (беріліп жатқан нысан) жүгіреді және оны екінші жағында күтіп тұрған басқа спортшыға береді. Атауға назар аударсаңыз, SynchronousQueue белгілі бір себептермен осылай аталғанын түсінесіз, ол деректерді синхронды түрде басқа ағынға тасымалдайды ; ол жай ғана енгізу және шығудың орнына біреудің деректерді алуын күтеді (асинхронды операция). Егер сіз CSP және Ada-мен таныс болсаңыз, синхрондалған кезектердің ағындардың кездесуіне ұқсас екенін білесіз. Олар бір ағында жұмыс істейтін нысан кейбір ақпаратты, оқиғаны немесе тапсырманы беру үшін басқа ағындағы нысанмен синхрондау қажет болатын басқаруды тасымалдау құрылымдары үшін өте қолайлы. Алдыңғы көп ағынды бағдарламалау оқулықтарында күту және хабарлау және BlockingQueue әдістерін пайдаланып өндіруші-тұтынушы мәселесін шешу жолын үйрендік . Енді SynchronousQueue көмегімен өндіруші-тұтынушы үлгісін қалай қолдану керектігін үйренеміз . Бұл сынып өндіруші мен тұтынушы ағындарының күтулеріне тапсырыс беру үшін әділ мінез-құлықты қосымша қолдайды. Әдепкі бойынша, бұл тапсырысқа кепілдік берілмейді. Дегенмен, әділ сипаттармен жасалған кезектер FIFO (бірінші кірген бірінші шығыс) кезектегі ағындарға қатынасуға кепілдік береді .
Java тілінде SynchronousQueue қолданатын өндіруші/тұтынушы.
Java тіліндегі SynchronousQueue мысалы - өндіруші тұтынушы - 1 мәселесін шешу Жоғарыда айтқанымдай, кез келген бағдарламалау тілінде ағын аралық байланысты түсіну үшін өндіруші-тұтынушы мәселесінен артық ештеңе жоқ. Бұл мәселеде бір жіп оқиғалар мен тапсырмаларды шығаратын өндіруші, ал екіншісі оны тұтынушы ретінде әрекет етеді. Ортақ буфер өндірушіден тұтынушыға деректерді тасымалдау үшін пайдаланылады. Бұл мәселені шешудің қиындығы төтенше жағдайларда туындайды, мысалы, өндіруші күтуге мәжбүр болған кезде... буфер толы немесе тұтынушы күтуге мәжбүр, себебі буфер бос. Бұл оңай шешілді, өйткені ... Блоктау кезегі деректерді сақтауға арналған буферді ғана емес, сонымен қатар ағынды басқаруды қамтамасыз етті, егер буфер толған болса, put() әдісін шақыратын ағынды блоктайды (Продюсер) және егер бұл болса take() әдісін шақыратын ағынды блоктайды (Тұтынушы). буфер бос болды. Енді біз дәл осы мәселені SynchronousQueue көмегімен шешеміз, бұл нөлдік сыйымдылығы бар параллель жинақтардың арнайы түрі. Келесі мысалда бізде PRODUCER және CONSUMER деп аталатын екі ағын бар (әрқашан ағындарға атау беріңіз, бұл көп ағынды бағдарламалаудың өте жақсы стилі).Бірінші ағын ойындағы ұпайды орналастырады, ал екінші ағын оны тұтынады. Ойындағы ұпай String түріндегі нысаннан басқа ештеңе емес. Бірақ егер сіз бағдарламаны басқа түрімен іске қоссаңыз, сіз ешқандай айырмашылықты байқамайсыз. SynchronousQueue қалай жұмыс істейтінін және өндіруші-тұтынушы мәселесін қалай шешуге болатынын түсіну үшін сізге қажет: не Eclipse ортасында отладка (отладка) бағдарламасын іске қосу , немесе тұтынушы.start(); егер тұтынушы ағыны іске қосылмаса, онда өндіруші ағын queue.put(оқиға) орнында блокталады; іске қосылса, продюсер [ПРОДЮСЕР] :FOUR оқиғасын жариялап жатқанын көре алмайсыз. Бұл орын алады, өйткені SynchronousQueue арнайы әрекеті, ол ағынды жариялау деректерінің басқа ағын деректерді алғанша және керісінше блоктауын қамтамасыз етеді. Кодтың қалған бөлігін production.start(); және тек тұтынушы ағынын бастау. Егер сіз бағдарламаның не шығаратынын мұқият зерттесеңіз, шығару реті керісінше екенін байқайсыз. [CONSUMER] ағыны деректерді [PRODUCER] ағыны шығарғанға дейін алған сияқты . Себебі, SynchronousQueue әдепкі бойынша кезекке кепілдік бермейді. Бірақ оның FIFO тәртібінде ағындарға қол жеткізуді белгілейтін әділдік ережелері бар. Бұл ережелерді шамадан тыс жүктелген SynchronousQueue конструкторына келесідей беру арқылы қосуға болады : import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
Java тіліндегі SynchronousQueue туралы нені есте сақтау керек.

Мұнда Java тіліндегі блоктау кезегінің осы ерекше түрінің кейбір маңызды қасиеттері берілген. Деректерді бір ағыннан екіншісіне синхрондалған түрде беру өте пайдалы. Бұл кезектің сыйымдылығы жоқ және басқа ағын оны босатқанша блокталады.

  1. SynchronousQueue блоктары және бір ағын деректерді қабылдауға дайын болғанша, екіншісі деректерді қоюға тырысады.
  2. SynchronousQueue бағдарламасының көлемі жоқ. Яғни, онда деректер жоқ.
  3. SynchronousQueue алға кезекке қою стратегиясын жүзеге асыру үшін пайдаланылады, мұнда ағын басқаруды күту ағынына береді немесе рұқсат етілсе, жаңасын жасайды, әйтпесе басқару тасымалданбайды.
  4. Бұл кезек нөлдік деректерге рұқсат бермейді. Нөлдік элементті қосу әрекеті NullPointerException шығарады .
  5. Жинақтағы басқа әдістерді (мысалы, құрамында) пайдалансаңыз, SynchronousQueue бос жинақ сияқты әрекет етеді.
  6. SynchronousQueue қарау әдісін пайдалана алмайсыз, себебі элемент оны жоюға әрекет жасағанда ғана бар; Сондай-ақ, басқа ағын оны жоюға әрекет етпейінше, элементтерді (кез келген әдісті қолдану арқылы) кірістіре алмайсыз.
  7. SynchronousQueue үшін итераторды пайдалана алмайсыз, себебі... оның элементтері жоқ.
  8. SynchronousQueue ағындарға қол жеткізу FIFO тәртібінде кепілдік берілген әділ ережелермен жасалуы мүмкін.
Мұның бәрі Java-дағы SynchronousQueue туралы болуы мүмкін. Біз осы көп ағынды топтаманың кейбір ерекше мүмкіндіктерін қарастырдық және Java тіліндегі SynchronousQueue көмегімен классикалық өндіруші-тұтынушы мәселесін шешу жолын білдік. Айтпақшы, оны Кезек деп атау мүлдем дұрыс емес, өйткені... оның құрамында элементтер жоқ. put() функциясына қоңырау басқа ағынды take() шақырмайынша аяқталмайды. Оны жіптердің бір an objectіге ортақтасатын жері ретінде қарастыру дұрысырақ. Басқаша айтқанда, бұл Java-да an objectілерді синхрондалған өткізуге арналған утorта, мүмкін күту және хабарлау әдісіне қауіпсіз балама .
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION