温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

异步加载缓存数据Java线程非阻塞优化

发布时间:2024-11-08 18:27:39 来源:亿速云 阅读:80 作者:小樊 栏目:编程语言

在Java中,异步加载缓存数据并实现线程非阻塞优化可以通过多种方式来实现。以下是一些常见的方法:

1. 使用CompletableFuture

CompletableFuture是Java 8引入的一个强大的异步编程工具,可以用来处理异步任务。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class AsyncCacheLoader {
    private final Cache<String, String> cache = new ConcurrentHashMap<>();

    public CompletableFuture<String> loadAsync(String key) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟从数据库或其他数据源加载数据
            return fetchDataFromDataSource(key);
        });
    }

    public String get(String key) {
        return cache.computeIfAbsent(key, this::loadAsync)
                     .thenApply(CompletableFuture::join)
                     .orTimeout(10, TimeUnit.SECONDS)
                     .exceptionally(ex -> {
                         System.err.println("Error loading data for key: " + key);
                         return null;
                     });
    }

    private String fetchDataFromDataSource(String key) {
        // 模拟从数据库或其他数据源加载数据
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Data for key: " + key;
    }

    public static void main(String[] args) {
        AsyncCacheLoader cacheLoader = new AsyncCacheLoader();
        cacheLoader.get("key1").thenAccept(System.out::println);
    }
}

2. 使用ExecutorService

ExecutorService是一个线程池,可以用来执行异步任务。

import java.util.concurrent.*;

public class AsyncCacheLoader {
    private final Cache<String, String> cache = new ConcurrentHashMap<>();
    private final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public Future<String> loadAsync(String key) {
        return executorService.submit(() -> {
            // 模拟从数据库或其他数据源加载数据
            return fetchDataFromDataSource(key);
        });
    }

    public String get(String key) {
        return cache.computeIfAbsent(key, this::loadAsync)
                     .get();
    }

    private String fetchDataFromDataSource(String key) {
        // 模拟从数据库或其他数据源加载数据
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Data for key: " + key;
    }

    public static void main(String[] args) {
        AsyncCacheLoader cacheLoader = new AsyncCacheLoader();
        try {
            System.out.println(cacheLoader.get("key1"));
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            cacheLoader.executorService.shutdown();
        }
    }
}

3. 使用ConcurrentHashMapcomputeIfAbsent方法

ConcurrentHashMap提供了computeIfAbsent方法,可以在缓存未命中时异步加载数据。

import java.util.concurrent.*;

public class AsyncCacheLoader {
    private final Cache<String, String> cache = new ConcurrentHashMap<>();
    private final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public String get(String key) {
        return cache.computeIfAbsent(key, key -> {
            // 模拟从数据库或其他数据源加载数据
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                return fetchDataFromDataSource(key);
            }, executorService);

            future.thenApply(data -> {
                cache.put(key, data);
                return data;
            });

            return future;
        });
    }

    private String fetchDataFromDataSource(String key) {
        // 模拟从数据库或其他数据源加载数据
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Data for key: " + key;
    }

    public static void main(String[] args) {
        AsyncCacheLoader cacheLoader = new AsyncCacheLoader();
        System.out.println(cacheLoader.get("key1"));
    }
}

4. 使用ScheduledExecutorService进行定时刷新

如果需要定期刷新缓存数据,可以使用ScheduledExecutorService

import java.util.concurrent.*;

public class AsyncCacheLoader {
    private final Cache<String, String> cache = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public AsyncCacheLoader() {
        scheduler.scheduleAtFixedRate(this::refreshCache, 0, 5, TimeUnit.SECONDS);
    }

    public String get(String key) {
        return cache.get(key);
    }

    private void refreshCache() {
        // 模拟从数据库或其他数据源加载数据
        for (String key : cache.keySet()) {
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                return fetchDataFromDataSource(key);
            }, executorService);

            future.thenApply(data -> {
                cache.put(key, data);
                return data;
            });
        }
    }

    private String fetchDataFromDataSource(String key) {
        // 模拟从数据库或其他数据源加载数据
        try {
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Data for key: " + key;
    }

    public static void main(String[] args) {
        AsyncCacheLoader cacheLoader = new AsyncCacheLoader();
        System.out.println(cacheLoader.get("key1"));
    }
}

通过这些方法,可以实现异步加载缓存数据并确保线程非阻塞,从而提高系统的性能和响应速度。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI