Fork/เข้าร่วม Framework เป็นการใช้งานอินเทอร์เฟซ ExecutorService ซึ่งเราสามารถใช้หลายกระบวนการได้ ส้อม/เข้าร่วมสามารถใช้เพื่อแยกงานขนาดใหญ่ซ้ำ ๆ ออกเป็นงานเล็ก ๆ หลายงานโดยมีเป้าหมายเพื่อใช้ประโยชน์จากทรัพยากรทั้งหมดเพื่อเพิ่มประสิทธิภาพของแอปพลิเคชันให้มากที่สุด
เช่นเดียวกับการใช้งานอินเทอร์เฟซ ExecutorService ใด ๆ Fork/เข้าร่วมยังใช้พูลเธรดเพื่อจัดการเธรดคนงานที่แจกจ่าย สิ่งที่ไม่เหมือนใครเกี่ยวกับเฟรมเวิร์กส้อม/เข้าร่วมคือมันใช้อัลกอริทึมการขโมยงาน ผ่านอัลกอริทึมนี้เธรดคนงานสามารถขโมยงานเธรดที่ยุ่งอื่น ๆ เพื่อดำเนินการเมื่อไม่มีอะไรสามารถทำได้
แกนกลางของ Fork/เข้าร่วมเฟรมเวิร์กคือคลาส ForkJoinpool ซึ่งเป็นคลาสย่อยของคลาส AbstractExecutorservice ForkJoinpool ใช้อัลกอริทึมการขโมยงานหลักและสามารถดำเนินการประมวลผล ForkJoinTask
การใช้งานขั้นพื้นฐาน
ขั้นตอนแรกในการใช้เฟรมเวิร์กส้อม/เข้าร่วมคือการเขียนโค้ดที่ทำงานที่แยกส่วน รหัสที่จะเขียนนั้นคล้ายกับรหัสหลอกต่อไปนี้:
หากงานมีขนาดเล็กพอ: ดำเนินการงานโดยตรง: ตัดงานออกเป็นสองงานเล็ก ๆ เพื่อดำเนินการงานเล็ก ๆ สองงานและรอผลลัพธ์
ใช้ subclass forkjointask เพื่อห่อหุ้มรหัสตามด้านบน โดยปกติแล้วจะมีการใช้คลาสบางคลาสที่จัดทำโดย JDK รวมถึง Recursivetask (คลาสนี้จะส่งคืนผลลัพธ์) และ RecursiveAction
หลังจากเตรียม subclass forkjointask ให้สร้างวัตถุที่แสดงถึงงานทั้งหมดและส่งผ่านไปยังวิธีการเรียกใช้ () ของอินสแตนซ์ forkjoinpool
จากความเบลอไปสู่การล้าง
เพื่อช่วยให้เข้าใจวิธีการทำงานของ Fork/เข้าร่วมเฟรมเวิร์กเราใช้เคสเพื่อแสดง: ตัวอย่างเช่นการเบลอรูปภาพ เราแสดงภาพโดยใช้อาร์เรย์จำนวนเต็มซึ่งแต่ละค่าตัวเลขแสดงถึงสีของพิกเซล ภาพเบลอนั้นแสดงด้วยอาร์เรย์ที่มีความยาวเท่ากัน
การดำเนินการเบลอทำได้โดยการประมวลผลแต่ละพิกเซลที่แสดงถึงภาพ คำนวณค่าเฉลี่ยของแต่ละพิกเซลและพิกเซลโดยรอบ (ค่าเฉลี่ยของสามสีหลักของสีแดงสีเหลืองและสีน้ำเงิน) และผลลัพธ์ที่ได้คือภาพที่เบลอ เนื่องจากการเป็นตัวแทนของภาพมักจะเป็นอาร์เรย์ขนาดใหญ่กระบวนการทั้งหมดมักจะใช้เวลามาก เฟรมเวิร์กส้อม/เข้าร่วมสามารถใช้เพื่อใช้ประโยชน์จากข้อดีของการประมวลผลพร้อมกันในระบบมัลติโปรเซสเซอร์เพื่อเร่งความเร็ว นี่คือการใช้งานที่เป็นไปได้:
แพ็คเกจ com.zhyea.robin; นำเข้า java.util.concurrent.recursiveaction; Forkblur คลาสสาธารณะขยายการเรียกคืน {ส่วนตัว int [] msource; ส่วนตัว int mstart; ความยาว int ส่วนตัว; int ส่วนตัว [] mdestination; // จัดการขนาดหน้าต่าง; มันจะต้องเป็นตัวเลขคี่ private int mblurwidth = 15; public forkblur (int [] src, int start, ความยาว int, int [] dst) {msource = src; mStart = เริ่ม; mLength = ความยาว; mdestination = dst; } void protected computedirectly () {int sidepixels = (mblurwidth - 1) / 2; สำหรับ (int index = mstart; index <mstart+mlength; index ++) {// คำนวณค่าเฉลี่ย float rt = 0, gt = 0, bt = 0; สำหรับ (int mi = -sidepixels; mi <= sidepixels; mi ++) {int mindex = math.min (math.max (mi+index, 0), msource.length - 1); int pixel = msource [mindex]; rt += (ลอย) ((พิกเซล & 0x00ff0000) >> 16) / mblurwidth; gt += (ลอย) ((พิกเซล & 0x00000ff00) >> 8) / mblurwidth; bt += (ลอย) ((พิกเซล & 0x000000ff) >> 0) / mblurwidth; } // จัดระเบียบพิกเซลเป้าหมายใหม่ int dpixel = (0xff0000000) | (((int) RT) << 16) | (((int) gt) << 8) | (((int) bt) << 0); mdestination [ดัชนี] = dpixel; -ตอนนี้ใช้วิธีการ Abstract Method Compute () ซึ่งมีการดำเนินการทั้งสองแบบฟัซซี่และแยกงานออกเป็นสองงานเล็ก ๆ ที่นี่เราเพียงแค่ตัดสินใจว่าจะดำเนินงานโดยตรงหรือแบ่งออกเป็นสองงานเล็ก ๆ ตามความยาวของอาร์เรย์:
ได้รับการป้องกัน int sthreshold = 100000; Void Compute ที่ได้รับการป้องกัน () {ถ้า (mLength <sthreshold) {computedirectly (); กลับ; } int split = mLength / 2; Invokeall (ใหม่ forkblur (msource, mstart, แยก, mdestination), ใหม่ forkblur (msource, mstart + split, mlength - split, mdestination)); -เนื่องจากการใช้วิธีการข้างต้นถูกกำหนดไว้ในคลาสย่อยของการทำซ้ำสามารถสร้างงานและทำงานโดยตรงใน forkjoinpool ขั้นตอนเฉพาะมีดังนี้:
1. สร้างวัตถุที่แสดงถึงงานที่จะดำเนินการ:
// SRC แสดงถึงอาร์เรย์ของพิกเซลของภาพต้นฉบับ // DST แสดงถึงพิกเซลของภาพที่สร้างขึ้น forkblur fb = ใหม่ forkblur (src, 0, src.length, dst);
2. สร้างอินสแตนซ์ forkjoinpool ที่ทำงาน:
ForkJoinPool pool = new ForkJoinPool();
3. เรียกใช้งาน:
pool.invoke(fb);
ซอร์สโค้ดยังมีรหัสบางส่วนเพื่อสร้างภาพเป้าหมาย สำหรับรายละเอียดอ้างอิงตัวอย่าง Forkblur
การใช้งานมาตรฐาน
ในการใช้เฟรมเวิร์ก Fork/เข้าร่วมเพื่อดำเนินการงานที่เกิดขึ้นพร้อมกันในระบบมัลติคอร์ตามอัลกอริทึมที่กำหนดเองแน่นอนคุณต้องใช้คลาสที่กำหนดเอง (เช่นคลาส Forkblur ที่เรานำไปใช้ก่อนหน้านี้) นอกจากนี้คุณสมบัติบางอย่างของเฟรมเวิร์กส้อม/เข้าร่วมได้ถูกนำมาใช้กันอย่างแพร่หลายใน Javase ตัวอย่างเช่นวิธี Parallelsort () ของคลาส Java.util.Arrays ใน Java8 ใช้เฟรมเวิร์กส้อม/เข้าร่วม สำหรับรายละเอียดโปรดดูเอกสาร Java API
การใช้งานเฟรมเวิร์ก Fork/เข้าร่วมอีกครั้งอยู่ภายใต้แพ็คเกจ Java.util.streams ซึ่งเป็นส่วนหนึ่งของคุณสมบัติ Lambda ของ Java8