JavaRush /Java блогу /Random-KY /Javaдагы SynchronousQueue мисалы - Продюсер Керектөөчү ма...
profeg
Деңгээл

Javaдагы SynchronousQueue мисалы - Продюсер Керектөөчү маселесин чечүү

Группада жарыяланган
Javaдагы SynchronousQueue мисалы - Продюсер Керектөөчү маселесин чечүү
SynchronousQueue BlockingQueue өзгөчө түрү болуп саналат, мында ар бир киргизүү операциясы башка жипте тиешелүү алып салуу буйругун күтүшү керек жана тескерисинче. SynchronousQueue боюнча put() ыкмасын чакырганыңызда , ал башка жип андан ошол элементти алганга чейин бөгөттөлөт. Демек, эгерде башка жип андан элементти алып салууга аракет кылса жана элемент жок болсо, анда ал жип башка жип элементти кезекке койгонго чейин блоктолот . Сиз SynchronousQueueди Олимпиада оту менен чуркаган спортчу ( жип ) деп ойлосоңуз болот, ал факел менен (өткөрүлүп жаткан an object) чуркап, аны башка тарапта күтүп турган башка спортчуга өткөрүп берет. Эгер атка көңүл бурсаңыз, SynchronousQueue кандайдыр бир себеп менен ушундай аталып калганын түшүнөсүз, ал маалыматтарды синхрондуу түрдө башка жипке өткөрөт ; ал жөн гана киргизип, чыгуунун ордуна кимдир бирөө маалыматтарды алуусун күтөт (асинхрондук операция). Эгер сиз CSP жана Ada менен тааныш болсоңуз, анда синхрондуу кезектер жиптердин жолугушуусуна окшош экенин билесиз. Алар бир жипте иштеген an object кандайдыр бир маалыматты, окуяны же тапшырманы өткөрүп берүү үчүн башка жиптеги an object менен синхрондоштурууга тийиш болгон башкаруу өткөрүп берүү конструкциялары үчүн абдан ылайыктуу. Мурунку көп агымдуу программалоо үйрөткүчтөрүндө күтүү жана кабарлоо жана BlockingQueue ыкмаларын колдонуу менен өндүрүүчү менен керектөөчүнүн көйгөйүн кантип чечүүнү үйрөндүк . Эми биз SynchronousQueue аркылуу өндүрүүчү-керектөөчү үлгүсүн кантип колдонууну үйрөнөбүз . Бул класс кошумча түрдө өндүрүүчүнүн жана керектөөчү жиптердин күтүүсүнө буйрук берүү үчүн адилеттүү жүрүм-турумду колдойт. Демейки боюнча, бул буйрутма кепилдик берилбейт. Бирок, адилеттүү касиеттери менен түзүлгөн кезектер FIFO (Биринчи чыккан) кезектеги жиптерге кирүүгө кепилдик берет .
Java'да SynchronousQueue колдонгон продюсер/Керектөөчү.
Javaдагы SynchronousQueue мисалы - Продюсер Керектөөчү маселесин чечүү - 1Мен жогоруда айткандай, продюсер менен керектөөчүнүн көйгөйүнөн башка программалоо тилдеринин ортосундагы байланышты түшүнүү үчүн эч нерсе жок . Бул маселеде бир жип окуяларды жана тапшырмаларды чыгаруучу продюсердин милдетин аткарса, экинчи жип анын керектөөчүсү катары иштейт. Бөлүштүрүлгөн буфер маалыматтарды өндүрүүчүдөн керектөөчүгө өткөрүү үчүн колдонулат. Бул көйгөйдү чечүүнүн кыйынчылыгы, мисалы, өндүрүүчү күтүүгө аргасыз болгондо, өзгөчө учурларда келип чыгат, анткени... буфер толуп же керектөөчү күтүүгө аргасыз, анткени буфер бош. Бул оңой чечилди, анткени... Бөгөттөө кезеги маалыматтарды сактоо үчүн буферди гана эмес, ошондой эле агымды башкарууну камсыз кылды, буфер толгон болсо, put() ыкмасын (Продюсер) чакырган жипти бөгөттөп, жана эгерде буфер бош болчу. Эми биз ушул эле маселени SynchronousQueue, нөл сыйымдуулугу менен параллелдүү коллекциялардын өзгөчө түрүн колдонуп чечебиз . Төмөнкү мисалда бизде PRODUCER жана КЕРЕКТҮҮ деп аталган эки жип бар (ар дайым жиптерге аттарды бериңиз, бул көп жиптүү программалоонун абдан жакшы стor). Биринчи жип оюндагы упайларды жайгаштырат, ал эми экинчи жип аны жейт. Оюндагы балл String түрүндөгү an objectтен башка эч нерсе эмес. Бирок программаны башка түр менен иштетсеңиз, эч кандай айырманы байкабай каласыз. SynchronousQueue кантип иштээрин жана продюсер менен керектөөчүнүн көйгөйүн кантип чечүү керектигин түшүнүү үчүн, сизге керек: же Eclipse чөйрөсүндө мүчүлүштүктөрдү оңдоо (дебаг) үчүн программаны иштетиңиз , же жөн гана customer.start(); эгерде керектөөчү жип иштебей жатса, анда өндүрүүчү жип queue.put(event) дарегинде бөгөттөлөт; эгер иштетилсе, продюсер [PRODUCER] :FOUR окуясын жарыялап жатканын көрө албайсыз. Бул болот, анткени SynchronousQueue спецификалык жүрүм-туруму, ал жипти жайгаштыруу берorштери башка жип дайындарды алганга чейин бөгөттөлө турганын жана тескерисинче. Коддун калган бөлүгүн продюсер.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 үнүн көлөмү жок. Башкача айтканда, ал маалыматтарды камтыbyte.
  3. SynchronousQueue алдыга кезекке туруу стратегиясын ишке ашыруу үчүн колдонулат, мында жип башкарууну күтүүчү жипке өткөрүп берет, же уруксат берилсе, жаңысын түзөт, антпесе башкаруу өткөрүлбөйт.
  4. Бул кезек нөл берorштерге жол бербейт. Нөл элементти кошуу аракети NullPointerException ыргытат .
  5. Коллекциянын башка ыкмаларын (мисалы, камтыган) колдонсоңуз, SynchronousQueue өзүн бош коллекциядай аткарат.
  6. Сиз SynchronousQueue'нун кароо ыкмасын колдоно албайсыз, анткени элемент сиз аны алып салууга аракет кылганыңызда гана бар; Ошондой эле, башка жип аны алып салууга аракет кылмайынча, элементтерди (кандайдыр бир ыкманы колдонуу менен) киргизе албайсыз.
  7. SynchronousQueue үчүн итераторду колдоно албайсыз, анткени... анын эч кандай элементтери жок.
  8. SynchronousQueue адилет эрежелер менен түзүлүшү мүмкүн, мында жиптерге кирүү FIFO тартибинде кепилденет.
Балким, мунун баары Javaдагы SynchronousQueue жөнүндө. Биз бул көп жиптүү коллекциянын айрым өзгөчөлүктөрүн карап чыктык жана Javaдагы SynchronousQueue аркылуу классикалык өндүрүүчү-керектөөчү көйгөйүн кантип чечүүнү үйрөндүк. Айтмакчы, аны Кезек деп айтуу таптакыр туура эмес, анткени... ал элементтерди камтыbyte. put() чалуу башка жипке take() чалмайынча бүтпөйт. Аны жиптердин биригип турган жери, алар бир an objectти бөлүшкөн жер деп түшүнүү туурараак. Башкача айтканда, бул Java-да an objectтерди синхрондоштуруу үчүн утorта, балким күтүү жана кабарлоо ыкмасына коопсуз альтернатива .
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION