Əsas məzmuna keçin

Java CyclicBarrier

CyclicBarrier Nədir?​

CyclicBarrier müəyyən sayda thread-in bir nöqtədə toplanmasını və hamısı gələnə qədər gözləməsini təmin edən synchronization vasitəsidir. Bütün thread-lər barrier-ə çatdıqda, hamısı eyni anda davam edir.

Xüsusiyyətlər:

  • Reusable - Təkrar istifadə edilə bilər
  • Bütün thread-lər await() çağırmalıdır
  • Barrier açıldıqdan sonra yenidən istifadə edilir
  • Barrier action - Hamısı çatdıqda icra olunan əlavə əməliyyat

Basic Usage​

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
public static void main(String[] args) {
int threadCount = 3;
CyclicBarrier barrier = new CyclicBarrier(threadCount);

for (int i = 1; i <= threadCount; i++) {
final int workerId = i;
new Thread(() -> {
try {
System.out.println("Worker " + workerId + " hazırlanır");
Thread.sleep(workerId * 1000);

System.out.println("Worker " + workerId + " barrier-də gözləyir");
barrier.await(); // Hamısı gələnə qədər gözlə

System.out.println("Worker " + workerId + " davam edir");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}

Barrier Action​

class BarrierActionExample {
public void runWithBarrierAction() {
int parties = 3;

// Hamısı çatdıqda bu action icra olunur
Runnable barrierAction = () -> {
System.out.println("=== Bütün thread-lər barrier-ə çatdı ===");
};

CyclicBarrier barrier = new CyclicBarrier(parties, barrierAction);

for (int i = 1; i <= parties; i++) {
final int id = i;
new Thread(() -> {
try {
System.out.println("Thread " + id + " işləyir");
Thread.sleep(id * 1000);
System.out.println("Thread " + id + " barrier-də");
barrier.await();
System.out.println("Thread " + id + " davam edir");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}

Reusable Barrier​

class ReusableBarrierExample {
public void multiplePhases() throws Exception {
int workers = 3;
CyclicBarrier barrier = new CyclicBarrier(workers);

for (int i = 1; i <= workers; i++) {
final int workerId = i;
new Thread(() -> {
try {
// Phase 1
System.out.println("Worker " + workerId + " - Phase 1");
barrier.await(); // 1-ci barrier

// Phase 2
System.out.println("Worker " + workerId + " - Phase 2");
barrier.await(); // 2-ci barrier (reuse)

// Phase 3
System.out.println("Worker " + workerId + " - Phase 3");
barrier.await(); // 3-cü barrier (reuse)

System.out.println("Worker " + workerId + " - Bitdi");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}

Matrix Hesablama​

class MatrixCalculation {
private final int workers = 4;
private final CyclicBarrier barrier;
private final double[][] matrix;

public MatrixCalculation(int size) {
this.matrix = new double[size][size];

// Hər iterasiyadan sonra barrier
this.barrier = new CyclicBarrier(workers, () -> {
System.out.println("İterasiya tamamlandı");
});
}

public void calculate() {
for (int i = 0; i < workers; i++) {
final int workerId = i;
new Thread(() -> {
try {
for (int iteration = 0; iteration < 10; iteration++) {
// Hər worker öz hissəsini hesablayır
calculatePartition(workerId);

// Hamısı bitənə qədər gözlə
barrier.await();
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}

private void calculatePartition(int workerId) {
int partitionSize = matrix.length / workers;
int start = workerId * partitionSize;
int end = (workerId + 1) * partitionSize;

for (int i = start; i < end; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] = Math.random();
}
}
}
}
class ParallelSearch {
private final List<Integer> data;
private final int target;
private final int workers = 4;
private volatile boolean found = false;
private final CyclicBarrier barrier;

public ParallelSearch(List<Integer> data, int target) {
this.data = data;
this.target = target;
this.barrier = new CyclicBarrier(workers, () -> {
if (found) {
System.out.println("Tapıldı!");
} else {
System.out.println("Bu mərhələdə tapılmadı");
}
});
}

public void search() {
int partitionSize = data.size() / workers;

for (int i = 0; i < workers; i++) {
final int workerId = i;
final int start = workerId * partitionSize;
final int end = (workerId == workers - 1) ?
data.size() : (workerId + 1) * partitionSize;

new Thread(() -> {
try {
for (int j = start; j < end; j++) {
if (data.get(j) == target) {
found = true;
System.out.println("Worker " + workerId +
" tapıldı index: " + j);
break;
}
}
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}

await() with Timeout​

class TimeoutBarrierExample {
public void processWithTimeout() {
CyclicBarrier barrier = new CyclicBarrier(3);

// 2 thread barrier-ə çatır
for (int i = 1; i <= 2; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() +
" barrier-də gözləyir");
barrier.await(5, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() +
" davam edir");
} catch (TimeoutException e) {
System.out.println(Thread.currentThread().getName() +
" timeout!");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}

// 3-cü thread gəlmir - timeout olacaq
}
}

Barrier Reset​

class BarrierResetExample {
public void demonstrateReset() {
CyclicBarrier barrier = new CyclicBarrier(3);

// 2 thread başlayır
for (int i = 1; i <= 2; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() +
" gözləyir");
barrier.await();
} catch (BrokenBarrierException e) {
System.out.println(Thread.currentThread().getName() +
" - Barrier broken!");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}

try {
Thread.sleep(1000);
System.out.println("Barrier reset edilir");
barrier.reset(); // Gözləyən thread-lər BrokenBarrierException alır
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

Game Simulation​

class GameSimulation {
private final int players = 4;
private final CyclicBarrier turnBarrier;
private int currentRound = 0;

public GameSimulation() {
this.turnBarrier = new CyclicBarrier(players, () -> {
currentRound++;
System.out.println("=== Round " + currentRound + " başladı ===");
});
}

public void startGame() {
for (int i = 1; i <= players; i++) {
final int playerId = i;
new Thread(() -> {
try {
for (int round = 0; round < 5; round++) {
// Oyunçu move edir
makeMove(playerId, round);

// Bütün oyunçular move edənə qədər gözlə
turnBarrier.await();
}
System.out.println("Player " + playerId + " oyunu bitirdi");
} catch (Exception e) {
e.printStackTrace();
}
}, "Player-" + i).start();
}
}

private void makeMove(int playerId, int round) {
try {
Thread.sleep((int)(Math.random() * 1000));
System.out.println("Player " + playerId +
" round " + round + " move etdi");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

Best Practices​

  1. Thread sayını düzgün təyin edin:

    int parties = 3; // Dəqiq 3 thread await() çağırmalıdır
    CyclicBarrier barrier = new CyclicBarrier(parties);
  2. Barrier action istifadə edin:

    Runnable action = () -> System.out.println("Phase completed");
    CyclicBarrier barrier = new CyclicBarrier(3, action);
  3. Timeout istifadə edin:

    try {
    barrier.await(10, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
    // Handle timeout
    }
  4. BrokenBarrierException-ı handle edin:

    try {
    barrier.await();
    } catch (BrokenBarrierException e) {
    // Barrier broken, yenidən yaradın
    }

Common Use Cases​

  • Paralel alqoritmlər - Matrix hesablamaları, parallel processing
  • Simulation - Oyun simulations, multi-agent systems
  • Testing - Thread-lərin eyni anda başlaması
  • Iterative algorithms - Hər iterasiyada sync lazım olan alqoritmlər
  • Phased execution - Mərhələli icra

CyclicBarrier vs CountDownLatch​

CyclicBarrierCountDownLatch
ReusableBir dəfəlik
Hər thread await() çağırırcountDown() və await() ayrı
Fixed partiesCount aşağı düşür
Barrier action mövcuddurAction yoxdur
BrokenBarrierExceptionYoxdur
reset() metodu varreset() yoxdur

Nə Zaman CyclicBarrier?​

CyclicBarrier istifadə edin:

  • Təkrar istifadə lazımdırsa
  • Fixed sayda thread eyni nöqtədə görüşməlidir
  • Hər mərhələdə synchronization lazımdır
  • Barrier action lazımdır

CountDownLatch istifadə edin:

  • Bir dəfəlik istifadə
  • Thread-lər count down edə bilər
  • Main thread digər thread-ləri gözləyir