Java'da gerçek eşzamanlı istekleri nasıl simüle edebilirim?

Bazen belirli bir işlevin eşzamanlı performansını test etmeniz gerekir ve başka araçlara başvurmak istemezsiniz, yalnızca kendi geliştirme dilinizi kullanın ve eşzamanlı bir istekte bulunmak en uygun yoldur.

Java'da eşzamanlı istekleri simüle etmek, birkaç iş parçacığı daha açtığınız ve istekleri başlattığınız sürece doğal olarak çok kullanışlıdır. Ancak, bu tür bir istek genellikle başlama sırasına sahiptir ve bu gerçek eşzamanlı eşzamanlılık olarak kabul edilemez! Gerçek eşzamanlı eşzamanlılığı nasıl sağlayabiliriz? Bu makalenin bahsetmek istediği nokta budur.Java, bu tür şeyler için en uygun olan mandallı CountDownLatch sağlar.

sadece şunlara ihtiyaç var:

  • N iş parçacığı açın, bir kilit ekleyin, tüm konuları açın;
  • Tüm iş parçacıkları hazır olduktan sonra, eşzamanlı istekleri gerçekten başlatmak için aç düğmesine basın.
  • paket com.test; java.io.BufferedReader'ı içe aktarın; java.io.IOException ithalatı; java.io.InputStream'i içe aktarın; java.io.InputStreamReader'ı içe aktarın; java.io.OutputStream içe aktarımı; java.net.HttpURLConnection'ı içe aktar; java.net.MalformedURLException ithal; java.net.URL dosyasını içe aktarın; import java.util.concurrent.CountDownLatch; public class LatchTest { public static void main (String args) InterruptedException {atar Runnable taskTemp = new Runnable () { // Bunun iş parçacığı açısından güvenli olmadığını unutmayın, bir boşluk bırakın özel int iCounter; @Override public void run () { for (int i = 0; i < 10; i ++) { // bir istek başlat // HttpClientOp.doGet ("https://www.baidu.com/"); iCounter ++; System.out.println (System.nanoTime () + "iCounter =" + iCounter); Deneyin { Thread.sleep (100); } catch (InterruptedException e) { e.printStackTrace (); } } } }; LatchTest latchTest = new LatchTest (); latchTest.startTaskAllInOnce (5, taskTemp); } public long startTaskAllInOnce (int threadNums, son Runnable görevi) InterruptedException { final CountDownLatch startGate = new CountDownLatch (1); final CountDownLatch endGate = new CountDownLatch (threadNums); for (int i = 0; i < threadNums; i ++) { Konu t = yeni Konu () { public void run () { Deneyin { // İplikleri burada bekletir, kapı açıldığında birlikte kapıda olurlar startGate.await (); Deneyin { task.run (); } en sonunda { // Uç kapıyı 1 küçültün ve 0'a düşürüldüğünde uç kapak açılabilir endGate.countDown (); } } catch (InterruptedException yani) { ie.printStackTrace (); } } }; t.start (); } long startTime = System.nanoTime (); System.out.println (startTime + "Tüm iş parçacığı hazır, eşzamanlı gidiyor ..."); // Kapıyı açmak için yalnızca bir anahtara ihtiyaç duyulduğundan, başlangıç kapısını hemen açın startGate.countDown (); // kapı açılıncaya kadar bekle endGate.await (); long endTime = System.nanoTime (); System.out.println (endTime + "Tüm iş parçacığı tamamlandı."); dönüş endTime-startTime; } }

    Uygulama etkisi aşağıdaki şekilde gösterilmektedir:

    httpClientOp araç sınıfı, olgun bir araç seti kullanabilir veya kendiniz kısa bir erişim yöntemi yazabilirsiniz, aşağıdakilere bakın:

    class HttpClientOp { public static String doGet (String httpurl) { HttpURLConnection bağlantısı = boş; InputStream = boş; BufferedReader br = null; String sonucu = null; // Sonuç dizesini döndür Deneyin { // Uzak url bağlantı nesnesi oluştur URL url = yeni URL (httpurl); // Uzak url bağlantı nesnesi üzerinden bir bağlantı açın ve bunu httpURLConnection sınıfına zorlayın bağlantı = (HttpURLConnection) url.openConnection (); // Bağlantı yöntemini ayarlayın: get connection.setRequestMethod ("GET"); // Ana sunucuya bağlanmak için zaman aşımı süresini ayarlayın: 15000 milisaniye connection.setConnectTimeout (15000); // Uzaktan kumanda tarafından döndürülen verilerin okunacağı zamanı ayarlayın: 60000 milisaniye connection.setReadTimeout (60000); // istek gönder connection.connect (); // Giriş akışını almak için bağlantı yoluyla bağlanın if (connection.getResponseCode () == 200) { is = connection.getInputStream (); // Giriş akışını kapsülleyin ve karakter kümesini belirtin br = new BufferedReader (yeni InputStreamReader ("UTF-8")); // verileri sakla StringBuffer sbf = new StringBuffer (); Dize sıcaklığı = boş; while ((temp = br.readLine ())! = null) { sbf.append (temp); sbf.append ("\ r \ n"); } sonuç = sbf.toString (); } } catch (MalformedURLException e) { e.printStackTrace (); } catch (IOException e) { e.printStackTrace (); } en sonunda { // kaynağı kapat eğer (null! = br) { Deneyin { br.close (); } catch (IOException e) { e.printStackTrace (); } } eğer (null! = is) { Deneyin { yakın(); } catch (IOException e) { e.printStackTrace (); } } connection.disconnect (); // Uzak bağlantıyı kapatın } dönüş sonucu; } public statik String doPost (String httpUrl, String parametresi) { HttpURLConnection bağlantısı = boş; InputStream = boş; OutputStream os = boş; BufferedReader br = null; Dize sonucu = boş; Deneyin { URL url = yeni URL (httpUrl); // Uzak url bağlantı nesnesi üzerinden bağlantıyı aç bağlantı = (HttpURLConnection) url.openConnection (); // Bağlantı isteği yöntemini ayarla connection.setRequestMethod ("POST"); // Ana sunucuya bağlanmak için zaman aşımı süresini ayarlayın: 15000 milisaniye connection.setConnectTimeout (15000); // Ana makine sunucusu tarafından döndürülen verileri okumak için zaman aşımını ayarlayın: 60000 milisaniye connection.setReadTimeout (60000); // Varsayılan değer: false, uzak bir sunucuya veri gönderirken / yazarken, bunun true olarak ayarlanması gerekir connection.setDoOutput (true); // Varsayılan değer: true, şu anda uzak hizmete veri okunurken true olarak ayarlanır, bu parametre isteğe bağlıdır connection.setDoInput (true); // Gelen parametrelerin biçimini ayarlayın: istek parametreleri ad1 = değer1ad2 = değer2 biçiminde olmalıdır. connection.setRequestProperty ("İçerik Türü", "uygulama / x-www-form-urlencoded"); // Kimlik doğrulama bilgilerini ayarlayın: Yetkilendirme: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0 connection.setRequestProperty ("Yetkilendirme", "Taşıyıcı da3efcbf-0845-4fe3-8aba-ee040be542c0"); // Bağlantı nesnesi aracılığıyla bir çıktı akışı alın os = connection.getOutputStream (); // Parametreyi çıktı akışı nesnesi aracılığıyla yazın / iletin, bayt dizisi aracılığıyla yazılır os.write (param.getBytes ()); // Bağlantı nesnesi aracılığıyla bir giriş akışı elde edin ve onu uzaktan okuyun if (connection.getResponseCode () == 200) { is = connection.getInputStream (); // Giriş akışı nesnesini sarın: karakter kümesi, çalışma öğesi grubunun gereksinimlerine göre ayarlanır br = new BufferedReader (yeni InputStreamReader ("UTF-8")); StringBuffer sbf = new StringBuffer (); Dize sıcaklığı = boş; // Verileri okumak için satır satır döngü yapın while ((temp = br.readLine ())! = null) { sbf.append (temp); sbf.append ("\ r \ n"); } sonuç = sbf.toString (); } } catch (MalformedURLException e) { e.printStackTrace (); } catch (IOException e) { e.printStackTrace (); } en sonunda { // kaynağı kapat eğer (null! = br) { Deneyin { br.close (); } catch (IOException e) { e.printStackTrace (); } } eğer (null! = os) { Deneyin { os.close (); } catch (IOException e) { e.printStackTrace (); } } eğer (null! = is) { Deneyin { yakın(); } catch (IOException e) { e.printStackTrace (); } } // Uzak adres url'sinden bağlantıyı kes connection.disconnect (); } dönüş sonucu; } }

    Yukarıdaki gibi, gerçek bir eşzamanlı istek başlatabilirsiniz.

    Eşzamanlı istek işlem sürecinin şematik diyagramı aşağıdaki gibidir:

    Tüm iş parçacıklarının aynı anda etkili olmasını sağlamak için burada bir kapı ayarlanır. Bununla birlikte, buradaki eşzamanlı aktivasyon yalnızca dil seviyesinde bir şeydir ve kesinlikle eşzamanlı değildir. Spesifik çağrı ayrıca CPU sayısına, iş parçacığı sayısına ve işletim sisteminin iş parçacığı zamanlama işlevine bağlıdır, ancak bunlar için endişelenmemize gerek yok, anahtar ilkeyi anlamaktır!

    CountDownLatch'e benzer şekilde, CyclicBarrier alet çiti de vardır, bu aynı zamanda tüm iş parçacığının belirli bir noktaya ulaşmasını beklemek ve ardından birlikte bir eylem başlatmak için bir araç sağlar, etki aynıdır, ancak çitin amacı aslında nispeten saftır, yani tüm dişlerin gelmesini beklemek. Yukarıda bahsedilen CountDownLatch kilidi tüm iş parçacıkları geldikten sonra uygulanmasına rağmen, tetikleme noktası aslında son anahtardır, bu nedenle odak farklıdır.

    Çitin gerçek eş zamanlı eşzamanlılığı nasıl sağladığına kısaca bir göz atın. Örnekler aşağıdaki gibidir:

    // Kilit yapısına uygun public class LatchTest { public static void main (String args) InterruptedException {atar Runnable taskTemp = new Runnable () { özel int iCounter; @Override public void run () { // bir istek başlat // HttpClientOp.doGet ("https://www.baidu.com/"); iCounter ++; System.out.println (System.nanoTime () + "iCounter =" + iCounter); } }; LatchTest latchTest = new LatchTest (); // latchTest.startTaskAllInOnce (5, taskTemp); latchTest.startNThreadsByBarrier (5, taskTemp); } public void startNThreadsByBarrier (int threadNums, Runnable finishTask) InterruptedException { // Belirli değerleri başlatmak gibi çit kaldırıldığında eylemi ayarlayın CyclicBarrier bariyeri = new CyclicBarrier (threadNums, finishTask); // Çit eşiği ile tutarlı olan n iş parçacığı başlatın, yani hazırlanacak iş parçacığı sayısı gereksinime ulaştığında, çit henüz açılır, böylece birleşik bir kontrol etkisi elde edilir for (int i = 0; i < threadNums; i ++) { Thread.sleep (100); new Thread (yeni Karşı Görev (bariyer)). start (); } System.out.println (Thread.currentThread (). GetName () + "out over ..."); } } class CounterTask, Runnable { // Çitten geçin, genellikle daha zarif bir yol düşünün özel CyclicBarrier bariyeri; public CounterTask (son CyclicBarrier engeli) { this.barrier = bariyer; } public void run () { System.out.println (Thread.currentThread (). GetName () + "-" + System.currentTimeMillis () + "hazır ..."); Deneyin { // Burada beklemek için bir çit kurun ve pozisyona gelen iplik gereksinimleri karşıladığında kapıyı açabilir barrier.await (); } catch (InterruptedException e) { e.printStackTrace (); } catch (BrokenBarrierException e) { e.printStackTrace (); } System.out.println (Thread.currentThread (). GetName () + "-" + System.currentTimeMillis () + "başladı ..."); } }

    Operasyonun sonuçları şu şekildedir:

    Her birinin kendi uygulama senaryoları vardır, ancak anahtar talepte yatmaktadır. Bu makaledeki örneklerin ihtiyaçları söz konusu olduğunda, bireyler daha kontrol edilebilir olduğu için kilitleme kullanmaya daha isteklidir. Ancak çok fazla kod var, bu yüzden beğenip beğenmediğinize bakın!

    Kaynak:

    WeChat Kimliğini (ID: Taro Kaynak Kodu) arayarak, çeşitli Java kaynak kodu analizleri alabilirsiniz.

    Ayrıca, [Kitaplar] 'a yanıt verdikten sonra, girişten mimariye kadar yazarın önerdiği çeşitli Java kitapları alabilirsiniz.

    Hadi, Sao Nian ~

    2020'de resmen piyasaya sürülen veya üretilen Audi e-tron
    önceki
    Bu hafta Instagram'da en iyi 10 spor ayakkabı! Veya o tanıdık eski yüzler?
    Sonraki
    Bahar Şenliği "hava göçü" sırasında hacim o kadar büyük değil ...
    TVB'nin Tayvan kutlama dramasının itibarı beklentileri aştı Yeşil yapraklar eve tekrar başarılı bir şekilde girdi ama 38 yaşında olduğunu düşünebilir misiniz?
    Murakami ortaya çıktığında hangi ayakkabıları giydi? UNIQLO UT x Murakami Takashi x DORAEMON yakaladınız mı?
    Paris Otomobil Fuarı'nda en ilginç 9 SUV olan gözlerinize şimdiden bayram edin
    En gelişmiş TVB çocuk yıldızı, şimdi bir çift oğlu ve kızı var, Lan Jieying ile unutulmaz bir işbirliği
    Spor ayakkabı oynamanın yeni yolları! Yıkım mı yoksa ayakkabıları göstermenin yeni bir yolu mu?
    Gerçekten kendini satacak mısın? ! Chery Holdings alım satım için listelenmiştir ve yeni hissedarlar hisseleri gerçekten elinde tutabilir!
    Taobao'ya başlayan mobilya kralı: 2.000 RMB'den 5 milyar RMB'ye, 5 yıl üst üste Çift 11 Şampiyonasını kazandı!
    Travis Scott x Air Jordan 4 mandalina ördeği rengiyle sürpriz mi yapıyor? ! Satışa çıkması bekleniyor mu?
    Gençlik hayalini taşıyan gerçek çekim Mahayana G70S / G60S / E20
    TVB evlenmemiş doğumları kabul ettikten sonra popüler adaylar, doğum günleri işte yapılacak
    Aynı Frekans Rezonansı 18. Disiplin Teftiş Merkez Komisyonunun Yedinci Genel Kurulunun ruhu SASAC ve merkezi işletmelerde uygulandı.
    To Top