Promosyon
Unibersidad ng Java
Pag-aaral
Mga kurso
Mga gawain
Mga Survey at Pagsusulit
Mga laro
Tulong
Iskedyul
Internship
Komunidad
Mga gumagamit
Forum
Chat
Mga artikulo
Mga kwento ng tagumpay
Aktibidad
Mga pagsusuri
Mga subscription
Banayad na tema
Artikulo
  • Mga pagsusuri
  • Tungkol sa atin
  • CS50
Magsimula
Simulan ang pag-aaral
  • Mga artikulo
  • Mga may-akda
  • Lahat ng grupo
  • Listahan ng Lahat ng Artikulo
JavaRush /Java Blog /Random-TL /Concurrency sa Java. Tutorial - Mga konstruksyon na ligta...
0xFF
Antas
  • 28 February 2021
  • 343 views
  • 0 comments

Concurrency sa Java. Tutorial - Mga konstruksyon na ligtas sa thread.

Nai-publish sa grupo
Java-университет
Pagkatapos tingnan ang mga pangunahing panganib ng pagpapatakbo ng mga parallel na programa (gaya ng atomicity o visibility ), titingnan natin ang ilang mga disenyo ng klase na makakatulong sa atin na maiwasan ang mga nabanggit na pitfalls. Lumilikha ang ilan sa mga construct na ito ng mga bagay na ligtas sa thread, na nagbibigay-daan sa aming ligtas na ibahagi ang mga ito sa pagitan ng mga thread. Bilang halimbawa, titingnan natin ang mga bagay na hindi nababago at walang estado. Pipigilan ng ibang mga view ang iba't ibang thread na baguhin ang data, gaya ng mga lokal na variable ng thread. Maaari mong tingnan ang lahat ng source code sa Github . 1. Immutable Object Ang mga hindi nababagong bagay ay may estado (may data na kumakatawan sa estado ng object), ngunit ito ay nakatakda sa oras ng paglikha sa constructor, kapag ang isang instance ng object ay nalikha at ang estado ay hindi na mababago. Bagama't maaaring magpalit-palit ang mga thread, mayroon pa ring isang posibleng estado ang isang bagay. Dahil ang lahat ng mga field ay read-only, walang thread ang makakapagpabago sa data ng object. Dahil dito, ang isang hindi nababagong stream ay likas na ligtas sa thread. Ang klase ng Produkto ay nagpapakita ng hindi nababagong klase. Pinupunan nito ang lahat ng field nito sa constructor at wala sa mga iyon ang nagbabago: public final class Product { private final String id; private final String name; private final double price; public Product(String id, String name, double price) { this.id = id; this.name = name; this.price = price; } public String getId() { return this.id; } public String getName() { return this.name; } public double getPrice() { return this.price; } public String toString() { return new StringBuilder(this.id).append("-").append(this.name) .append(" (").append(this.price).append(")").toString(); } public boolean equals(Object x) { if (this == x) return true; if (x == null) return false; if (this.getClass() != x.getClass()) return false; Product that = (Product) x; if (!this.id.equals(that.id)) return false; if (!this.name.equals(that.name)) return false; if (this.price != that.price) return false; return true; } public int hashCode() { int hash = 17; hash = 31 * hash + this.getId().hashCode(); hash = 31 * hash + this.getName().hashCode(); hash = 31 * hash + ((Double) this.getPrice()).hashCode(); return hash; } } Sa ilang mga kaso, hindi magiging sapat ang paggawa ng finals sa mga field. Halimbawa, ang klase ng MutableProduct ay hindi nababago, bagama't ang lahat ng mga field ay pinal: Bakit ang klase sa itaas ay hindi nababago? Ang dahilan ay pinapayagan namin ang isang reference na makuha mula sa isang klase. Ang field na ' categories ' ay isang nababagong sanggunian, kaya kapag natanggap, maaaring baguhin ito ng kliyente. Upang ilarawan ito, isaalang-alang ang sumusunod na programa: At ang console output: Dahil ang field na 'mga kategorya' ay nababago at nakuha mula sa isang bagay, binago ng kliyente ang listahang ito. Ang isang bagay na dapat ay hindi nababago ay nabago, na nagreresulta sa isang bagong estado. Kung gusto mong kumatawan sa mga nilalaman ng isang listahan, maaari kang gumamit ng isang hindi mababago na representasyon ng listahan: 2. Stateless Object Ang mga stateless na bagay ay katulad ng hindi nababago na mga bagay, ngunit sa kasong ito ay wala silang estado, kahit isa. Kapag ang isang bagay ay isang stateless object, hindi nito kailangang ipagpatuloy ang anumang data sa pagitan ng mga tawag. Dahil walang estado na umiiral, walang thread ang makakaapekto sa resulta ng isa pang thread sa pamamagitan ng pagtawag sa mga pamamaraan ng object. Para sa kadahilanang ito, ang mga bagay na walang estado ay likas na ligtas sa thread. Ang klase ng ProductHandler ay isang halimbawa ng ganitong uri ng bagay. Naglalaman ito ng maraming operasyon sa mga bagay ng Produkto, at hindi ito nag-iimbak ng anumang data sa pagitan ng mga tawag. Ang resulta ng operasyon ay independiyente sa mga nakaraang tawag o anumang nakaimbak na data: Sa paraan ng sumCart, kino-convert ng ProductHandler ang listahan ng Produkto sa isang array para magamit sa isang para sa bawat loop upang umulit sa lahat ng mga elemento. Ang listahan ng iterator ay hindi ligtas sa thread at maaaring magtapon ng ConcurrentModificationException kung may mga pagbabago sa panahon ng pag-ulit. Depende sa iyong mga pangangailangan, maaari kang pumili ng ibang diskarte . 3. Mga Lokal na Variable ng Thread Ang mga lokal na variable ng thread ay ang mga variable na tinukoy sa loob ng isang thread. Walang ibang mga thread ang nakakakita sa kanila at hindi ito babaguhin. Ang unang uri ay mga lokal na variable. Sa halimbawa sa ibaba, ang kabuuang variable ay naka-imbak sa stack ng thread: public final class MutableProduct { private final String id; private final String name; private final double price; private final List categories = new ArrayList<>(); public MutableProduct(String id, String name, double price) { this.id = id; this.name = name; this.price = price; this.categories.add("A"); this.categories.add("B"); this.categories.add("C"); } public String getId() { return this.id; } public String getName() { return this.name; } public double getPrice() { return this.price; } public List getCategories() { return this.categories; } public List getCategoriesUnmodifiable() { return Collections.unmodifiableList(categories); } public String toString() { return new StringBuilder(this.id).append("-").append(this.name) .append(" (").append(this.price).append(")").toString(); } } public static void main(String[] args) { MutableProduct p = new MutableProduct("1", "a product", 43.00); System.out.println("Product categories"); for (String c : p.getCategories()) System.out.println(c); p.getCategories().remove(0); System.out.println("\nModified Product categories"); for (String c : p.getCategories()) System.out.println(c); } Product categories A B C Modified Product categories B C public List getCategoriesUnmodifiable() { return Collections.unmodifiableList(categories); } public class ProductHandler { private static final int DISCOUNT = 90; public Product applyDiscount(Product p) { double finalPrice = p.getPrice() * DISCOUNT / 100; return new Product(p.getId(), p.getName(), finalPrice); } public double sumCart(List cart) { double total = 0.0; for (Product p : cart.toArray(new Product[0])) total += p.getPrice(); return total; } } public double sumCart(List cart) { double total = 0.0; for (Product p : cart.toArray(new Product[0])) total += p.getPrice(); return total; } Tandaan lamang na kung tutukuyin mo ang isang sanggunian sa halip na isang primitive na variable at ibabalik ito, aalis ito sa mga hangganan nito. Maaaring hindi mo alam kung saan ginawa ang ibinalik na link. Ang code na tumatawag sa paraan ng sumCart ay maaaring mag-imbak nito sa isang static na field at payagan itong ma-access ng iba't ibang mga thread. Ang pangalawang uri ay ang ThreadLocal class . Nagbibigay ang klase na ito ng independiyenteng imbakan para sa bawat thread. Ang mga value na nakaimbak sa ThreadLocal ay available sa anumang code sa parehong thread. Ang klase ng ClientRequestId ay nagpapakita ng isang halimbawa ng paggamit ng klase ng ThreadLocale: Ang klase ng ProductHandlerThreadLocal ay gumagamit ng ClientRequestId upang ibalik ang parehong nabuong ID sa parehong thread: Kapag isinasagawa ang pangunahing pamamaraan, ang output ng console ay magpapakita ng iba't ibang mga ID para sa bawat thread. Halimbawa: Kung gagamit ka ng ThreadLocale, kailangan mong pangalagaan ang ilang mga panganib sa paggamit kapag pinagsasama ang mga thread (tulad ng sa mga application ng server). Maaari kang makakuha ng mga pagtagas ng memorya o pagtagas ng impormasyon sa pagitan ng mga kahilingan. Hindi na ako magdetalye tungkol dito dahil... Ang artikulong " Paano i-shoot ang iyong sarili sa paa gamit ang ThreadLocale " ay mahusay na nagpapakita kung paano ito maaaring mangyari. 4. Paggamit ng synchronization Ang isa pang paraan upang magbigay ng thread-safe na access sa mga bagay ay sa pamamagitan ng synchronization. Kung i-synchronize namin ang lahat ng pag-access sa isang reference, pagkatapos ay isang thread object lang ang makaka-access dito sa isang partikular na oras. Tatalakayin natin ito sa mga susunod na post. 5. Konklusyon Tumingin kami sa ilang mga pamamaraan na nagbibigay-daan sa iyo upang bumuo ng mga simpleng bagay na maaaring ma-access ng maraming mga thread. Mas mahirap na pigilan ang mga multi-threaded na error kung ang isang bagay ay maaaring magkaroon ng maraming estado. Sa kabilang banda, kung ang isang bagay ay maaaring magkaroon lamang ng isang estado o wala, hindi namin kailangang mag-alala tungkol sa maraming mga thread na nag-a-access sa bagay nang sabay-sabay. Ang orihinal ay narito . public class ClientRequestId { private static final ThreadLocal id = new ThreadLocal () { @Override protected String initialValue() { return UUID.randomUUID().toString(); } }; public static String get() { return id.get(); } } public class ProductHandlerThreadLocal { //Same methods as in ProductHandler class public String generateOrderId() { return ClientRequestId.get(); } } T1 - 23dccaa2-8f34-43ec-bbfa-01cec5df3258 T2 - 936d0d9d-b507-46c0-a264-4b51ac3f527d T2 - 936d0d9d-b507-46c0-a264-4b51ac3f527d T3 - 126b8359-3bcc-46b9-859a-d305aff22c7e ...
Frontend-университет
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Matuto
  • Курси програмування
  • Pagpaparehistro
  • Kurso sa Java
  • Tulong sa Mga Gawain
  • Pagpepresyo
  • Mga Proyekto sa Laro
Komunidad
  • Mga gumagamit
  • Mga artikulo
  • Forum
  • Chat
  • Mga Kwento ng Tagumpay
  • Aktibidad
kumpanya
  • Tungkol sa atin
  • Mga contact
  • Mga pagsusuri
  • FAQ
  • Suporta
JavaRush Ang JavaRush ay isang online na kurso para sa pag-aaral ng Java programming mula sa simula. Ang kursong ito ay isang perpektong paraan upang makabisado ang Java para sa mga nagsisimula. Naglalaman ito ng 1200+ na gawain na may agarang pag-verify at isang mahalagang saklaw ng teorya ng Java fundamentals. Upang matulungan kang magtagumpay sa edukasyon, nagpatupad kami ng isang hanay ng mga tampok na motibasyon: mga pagsusulit, mga proyekto sa pag-coding, nilalaman tungkol sa mahusay na pag-aaral at karera ng developer ng Java.
Sundan mo kami
Ang mga Programmer ay Ginawa, Hindi Ipinanganak © 2025 JavaRush
I-download ang App
  • Google Play
  • App Store
Mastercard Visa
Ang mga Programmer ay Ginawa, Hindi Ipinanganak © 2025 JavaRush