Rumah  >  Artikel  >  Java  >  Terokai batasan dalam Java

Terokai batasan dalam Java

尊渡假赌尊渡假赌尊渡假赌
尊渡假赌尊渡假赌尊渡假赌ke hadapan
2024-01-02 10:28:411417semak imbas

Dalam dunia pembangunan perisian, mengurus penggunaan sumber secara berkesan dan memastikan penggunaan perkhidmatan yang adil adalah pertimbangan penting dalam membina aplikasi berskala dan mantap. Pendikitan ialah amalan mengawal kadar operasi tertentu dilakukan dan merupakan mekanisme utama untuk mencapai matlamat ini. Dalam artikel ini, kami akan mendalami pelbagai cara untuk melaksanakan pendikitan di Jawa dan memperkenalkan pelbagai strategi dengan contoh praktikal. .

Dalam dunia pembangunan perisian, mengurus penggunaan sumber secara berkesan dan memastikan penggunaan perkhidmatan yang adil adalah pertimbangan penting dalam membina aplikasi berskala dan mantap. Pendikitan ialah amalan mengawal kadar operasi tertentu dilakukan dan merupakan mekanisme utama untuk mencapai matlamat ini. Dalam artikel ini, kami akan mendalami pelbagai cara untuk melaksanakan pendikitan di Jawa dan memperkenalkan pelbagai strategi dengan contoh praktikal.

Penafian: Dalam artikel ini, saya akan menumpukan pada ilustrasi berbenang tunggal yang mudah menyelesaikan penyelesaian asas.

Fahami Had

Had melibatkan mengawal selia kekerapan tindakan tertentu dibenarkan berlaku. Ini amat penting dalam situasi di mana sistem perlu dilindungi daripada penyalahgunaan, memerlukan pengurusan sumber atau memerlukan akses adil kepada perkhidmatan yang dikongsi. Kes penggunaan biasa untuk pendikit termasuk mengehadkan kadar permintaan API, mengurus kemas kini data dan mengawal akses kepada sumber kritikal.

Penghad kadar penyekatan mudah - bukan untuk kegunaan pengeluaran! thread.sleep()

Cara mudah untuk melaksanakan had adalah dengan menggunakan kaedah ini untuk memperkenalkan kelewatan antara operasi berturut-turut. Walaupun kaedah ini mudah, ia mungkin tidak sesuai untuk senario berprestasi tinggi kerana sifat menyekatnya. Thread.sleep()

public class SimpleRateLimiter {

    private long lastExecutionTime = 0;
    private long intervalInMillis;

    public SimpleRateLimiter(long requestsPerSecond) {
        this.intervalInMillis = 1000 / requestsPerSecond;
    }

    public void throttle() throws InterruptedException {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - lastExecutionTime;

        if (elapsedTime < intervalInMillis) {
            Thread.sleep(intervalInMillis - elapsedTime);
        }

        lastExecutionTime = System.currentTimeMillis();
        // Perform the throttled operation
        System.out.println("Throttled operation executed at: " + lastExecutionTime);
    }
}

Dalam contoh ini, kelas ini membenarkan bilangan operasi tertentu untuk dilakukan sesaat. Jika masa berlalu antara operasi kurang daripada selang yang dikonfigurasikan, tempoh tidur diperkenalkan untuk mencapai kadar yang dikehendaki. SimpleRateLimiter

Basic Limitation of Waits

Mari kita mulakan dengan contoh mudah yang kita gunakan untuk mengehadkan pelaksanaan sesuatu kaedah. Matlamatnya adalah untuk membenarkan kaedah dipanggil hanya selepas masa bertenang tertentu telah berlalu. tunggu

public class BasicThrottling {

    private final Object lock = new Object();
    private long lastExecutionTime = 0;
    private final long cooldownMillis = 5000; // 5 seconds cooldown

    public void throttledOperation() throws InterruptedException {
        synchronized (lock) {
            long currentTime = System.currentTimeMillis();
            long elapsedTime = currentTime - lastExecutionTime;

            if (elapsedTime < cooldownMillis) {
                lock.wait(cooldownMillis - elapsedTime);
            }

            lastExecutionTime = System.currentTimeMillis();
            // Perform the throttled operation
            System.out.println("Throttled operation executed at: " + lastExecutionTime);
        }
    }
}

Dalam contoh ini, kaedah menggunakan kaedah ini untuk membuat benang menunggu tempoh bertenang untuk tamat. throttledOperationwait

Had dinamik dengan menunggu dan pemberitahuan

Mari tingkatkan contoh sebelumnya untuk memperkenalkan pendikitan dinamik, di mana tempoh bertenang boleh dilaraskan secara dinamik. Pengeluaran mesti mempunyai peluang untuk membuat perubahan dengan cepat.

public class DynamicThrottling {

    private final Object lock = new Object();
    private long lastExecutionTime = 0;
    private long cooldownMillis = 5000; // Initial cooldown: 5 seconds

    public void throttledOperation() throws InterruptedException {
        synchronized (lock) {
            long currentTime = System.currentTimeMillis();
            long elapsedTime = currentTime - lastExecutionTime;

            if (elapsedTime < cooldownMillis) {
                lock.wait(cooldownMillis - elapsedTime);
            }

            lastExecutionTime = System.currentTimeMillis();
            // Perform the throttled operation
            System.out.println("Throttled operation executed at: " + lastExecutionTime);
        }
    }

    public void setCooldown(long cooldownMillis) {
        synchronized (lock) {
            this.cooldownMillis = cooldownMillis;
            lock.notify(); // Notify waiting threads that cooldown has changed
        }
    }

    public static void main(String[] args) {
        DynamicThrottling throttling = new DynamicThrottling();

        for (int i = 0; i < 10; i++) {
            try {
                throttling.throttledOperation();
                // Adjust cooldown dynamically
                throttling.setCooldown((i + 1) * 1000); // Cooldown increases each iteration
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Dalam contoh ini, kami memperkenalkan kaedah melaraskan masa bertenang secara dinamik. Kaedah ini digunakan untuk membangunkan sebarang urutan menunggu, membolehkan mereka menyemak masa bertenang baharu. setCooldownnotify

Menggunakan semaphore Java

Kelas Java boleh digunakan sebagai alat berkuasa untuk pendikit. Semaphore mengekalkan satu set lesen, di mana setiap operasi perolehan menggunakan satu lesen dan setiap operasi pelepasan menambah satu lesen. Semaphore

public class SemaphoreRateLimiter {

    private final Semaphore semaphore;

    public SemaphoreRateLimiter(int permits) {
        this.semaphore = new Semaphore(permits);
    }

    public boolean throttle() {
        if (semaphore.tryAcquire()) {
            // Perform the throttled operation
            System.out.println("Throttled operation executed. Permits left: " + semaphore.availablePermits());
            return true;
        } else {
            System.out.println("Request throttled. Try again later.");
            return false;
        }
    }

    public static void main(String[] args) {
        SemaphoreRateLimiter rateLimiter = new SemaphoreRateLimiter(5); // Allow 5 operations concurrently

        for (int i = 0; i < 10; i++) {
            rateLimiter.throttle();
        }
    }
}

Dalam contoh ini, kelas menggunakan a dengan bilangan lesen yang ditentukan. Kaedah ini cuba mendapatkan lesen dan membenarkan operasi jika berjaya. SemaphoreRateLimiterSemaphorethrottle

Berbilang contoh dalam kotak

Frameworks seperti Spring atau Redis menyediakan pelbagai penyelesaian mudah.

Spring AOP untuk sekatan kaedah

Menggunakan keupayaan pengaturcaraan berorientasikan aspek (AOP) Spring, kami boleh mencipta mekanisme sekatan peringkat kaedah. Pendekatan ini membolehkan kami memintas panggilan kaedah dan menggunakan logik pendikit.

@Aspect
@Component
public class ThrottleAspect {

    private Map<String, Long> lastInvocationMap = new HashMap<>();

    @Pointcut("@annotation(throttle)")
    public void throttledOperation(Throttle throttle) {}

    @Around("throttledOperation(throttle)")
    public Object throttleOperation(ProceedingJoinPoint joinPoint, Throttle throttle) throws Throwable {
        String key = joinPoint.getSignature().toLongString();

        if (!lastInvocationMap.containsKey(key) || System.currentTimeMillis() - lastInvocationMap.get(key) > throttle.value()) {
            lastInvocationMap.put(key, System.currentTimeMillis());
            return joinPoint.proceed();
        } else {
            throw new ThrottleException("Request throttled. Try again later.");
        }
    }
}

Dalam contoh ini, kami telah menentukan anotasi tersuai dan aspek AOP() untuk memintas kaedah menggunakan . @ThrottleThrottleAspect@ThrottleThrottleAspect

Menggunakan Guava RateLimiter

Pustaka Guava Google menyediakan kelas yang memudahkan pelaksanaan had. Ia membolehkan menentukan kadar operasi dibenarkan. RateLimiter

Mari kita lihat cara ia boleh digunakan untuk mengehadkan kaedah: RateLimiter

import com.google.common.util.concurrent.RateLimiter;

@Component
public class ThrottledService {

    private final RateLimiter rateLimiter = RateLimiter.create(5.0); // Allow 5 operations per second

    @Throttle
    public void throttledOperation() {
        if (rateLimiter.tryAcquire()) {
            // Perform the throttled operation
            System.out.println("Throttled operation executed.");
        } else {
            throw new ThrottleException("Request throttled. Try again later.");
        }
    }
}

Dalam contoh ini, kami menggunakan Guava untuk mengawal kadar pelaksanaan sesuatu kaedah. Kaedah ini digunakan untuk menyemak sama ada operasi dibenarkan berdasarkan kadar yang ditetapkan. RateLimiterthrottledOperationtryAcquire

Redis sebagai mekanisme pengehad

Menggunakan stor data luaran seperti Redis, kami boleh melaksanakan mekanisme pendikitan teragih. Pendekatan ini amat berguna dalam persekitaran perkhidmatan mikro di mana beberapa keadaan perlu menyelaraskan kekangan.

@Component
public class RedisThrottleService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${throttle.key.prefix}")
    private String keyPrefix;

    @Value("${throttle.max.operations}")
    private int maxOperations;

    @Value("${throttle.duration.seconds}")
    private int durationSeconds;

    public void performThrottledOperation(String userId) {
        String key = keyPrefix + userId;
        Long currentCount = redisTemplate.opsForValue().increment(key);

        if (currentCount != null && currentCount > maxOperations) {
            throw new ThrottleException("Request throttled. Try again later.");
        }

        if (currentCount == 1) {
            // Set expiration for the key
            redisTemplate.expire(key, durationSeconds, TimeUnit.SECONDS);
        }

        // Perform the throttled operation
        System.out.println("Throttled operation executed for user: " + userId);
    }
}

Dalam contoh ini, kami menggunakan Redis untuk menyimpan dan mengurus kiraan operasi bagi setiap pengguna. Kaedah ini menambah kiraan dan menyemak sama ada had yang dibenarkan telah dicapai. performThrottledOperation

Conclusion

Pendikit memainkan peranan penting dalam mengekalkan kestabilan dan kebolehskalaan aplikasi anda. Dalam artikel ini, kami meneroka pelbagai cara untuk melaksanakan pendikitan dalam Java, termasuk teknik mudah untuk menggunakan dan menggunakan penyelesaian luar kotak. Thread.sleep()Semaphore

Pilihan strategi pendikit bergantung pada faktor seperti sifat aplikasi, keperluan prestasi dan tahap kawalan yang diperlukan. Apabila melaksanakan sekatan, anda mesti menyeimbangkan antara mencegah penyalahgunaan dan memastikan pengalaman pengguna yang responsif dan adil.

Apabila menyepadukan mekanisme pendikit ke dalam aplikasi anda, pertimbangkan untuk memantau dan melaraskan parameter berdasarkan corak penggunaan sebenar. Apabila membuat keputusan tentang pelaksanaan kekangan, beberapa pertanyaan mungkin timbul, seperti cara mengendalikan situasi di mana tugas melebihi tarikh akhir yang ditetapkan. Dalam artikel saya yang seterusnya, saya merancang untuk meneroka pelaksanaan Java yang mantap yang menangani pelbagai senario secara komprehensif.

Atas ialah kandungan terperinci Terokai batasan dalam Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:dzone.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam