Sobes.tech
Middle+

Έχετε εργαστεί με σημαφόρους στην πρακτική σας;

sobes.tech AI

Απάντηση από AI

Ναι, χρειάστηκε να χρησιμοποιήσω σημαφόρους, ειδικά στο πλαίσιο της εργασίας με πολυνηματικότητα σε εφαρμογές Android.

Οι σημαφόροι στη Java (java.util.concurrent.Semaphore) χρησιμοποιούνται για τον περιορισμό του αριθμού των νημάτων που μπορούν ταυτόχρονα να έχουν πρόσβαση σε μια συγκεκριμένη πόρο. Αυτό είναι χρήσιμο σε σενάρια όπου ο πόρος έχει περιορισμένη "χωρητικότητα", π.χ., μια ομάδα συνδέσεων ή ένας περιορισμένος αριθμός διαθέσιμων θέσεων.

Οι κύριες μέθοδοι με τις οποίες έχω εργαστεί είναι:

  • acquire(): Μπλοκάρει το τρέχον νήμα μέχρι να διατεθεί μια άδεια.
  • acquire(int permits): Μπλοκάρει το τρέχον νήμα μέχρι να διατεθούν ο αριθμός των αδειών που ορίζονται.
  • release(): Επιστρέφει μια άδεια στον σημαφόρο, αυξάνοντας τον αριθμό των διαθέσιμων αδειών.
  • release(int permits): Επιστρέφει τον αριθμό των αδειών που ορίζονται.
  • tryAcquire(): Προσπαθεί να αποκτήσει μια άδεια χωρίς να μπλοκάρει το νήμα.
  • availablePermits(): Επιστρέφει τον τρέχοντα αριθμό διαθέσιμων αδειών.

Παράδειγμα χρήσης:

import java.util.concurrent.Semaphore;

public class ResourcePool {

    private static final int MAX_AVAILABLE = 5;
    private final Semaphore permits = new Semaphore(MAX_AVAILABLE, true); // Δίκαιος σημαφόρος

    public void useResource() throws InterruptedException {
        permits.acquire(); // Αίτηση άδειας
        try {
            // Λογική χρήσης της πόρου (π.χ., εργασία με μια ομάδα συνδέσεων)
            System.out.println(Thread.currentThread().getName() + " χρησιμοποιεί την πόρο.");
            Thread.sleep(1000); // Προσομοίωση εργασίας με την πόρο
        } finally {
            permits.release(); // Απελευθέρωση άδειας
            System.out.println(Thread.currentThread().getName() + " τελείωσε τη χρήση της πόρου.");
        }
    }

    public static void main(String[] args) {
        ResourcePool pool = new ResourcePool();
        // Δημιουργία πολλαπλών νημάτων που θα προσπαθήσουν να χρησιμοποιήσουν την πόρο
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    pool.useResource();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

Σε αυτό το παράδειγμα, ο σημαφόρος permits αρχικοποιείται με 5 άδειες, που σημαίνει ότι μόνο 5 νήματα μπορούν ταυτόχρονα να βρίσκονται μέσα στο μπλοκ try που χρησιμοποιεί την πόρο. Η μέθοδος acquire() μπλοκάρει τα νήματα αν όλες οι άδειες είναι κατειλημμένες, μέχρι να καλέσουν άλλα νήματα το release().

Οι σημαφόροι είναι χρήσιμοι για τη διαχείριση πρόσβασης σε περιορισμένες ομάδες πόρων, αλλά πρέπει να προσέχετε πιθανά προβλήματα όπως deadlocks, αν η διαχείριση της λήψης και της απελευθέρωσης των αδειών δεν γίνεται σωστά. Η χρήση try με ένα μπλοκ finally για την κλήση release() είναι καλή πρακτική για να διασφαλίσετε την απελευθέρωση των πόρων ακόμα και σε περίπτωση εξαιρέσεων.