[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]使用google cache变相实现String的同步锁

上一篇:[备忘]java并发写文件,会导致内容错乱
下一篇:[备忘]官网 Troubleshooting Guide for Java SE 6 with HotSpot VM

添加日期:2021/10/25 13:29:37 快速返回   返回列表 阅读724次
直接使用String做同步锁,会发现不好使。
因为,只有常量池里的字符串(比如代码里直接赋值的),相同值才会返回同一个对象。
使用intern()又感觉有些浪费。


package com.example.demo.util;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

public class OSSUtil2 {

    /**
     * (缓存一分钟就过期).
     */
    private static Cache<String, Object> fileCache = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.MINUTES)
            .build();

    private OSSUtil2() {
    }

    public static void img() throws IOException {
        File file = new File("D:\\example-resize.jpg");

        for (int aa = 0; aa < 10; aa++) {
            final int x = aa;
            new Thread() {
                public void run() {
                    currentThread().setName("" + x);
                    for (int i = 0; i < 10; i++) {

                        // 按文件,分别做同步锁
                        String key = file.getAbsolutePath();

                        // 怕字符串不靠谱,使用对应的Object锁

                        // 如果不存在(新的entry),那么会向map中添加该键值对,并返回null。
                        // 如果已经存在,那么不会覆盖已有的值,直接返回已经存在的值。
                        Object lock = null;
                        Object newLock = new Object();
                        Object oldLock = fileCache.asMap().putIfAbsent(key, newLock);
                        if (oldLock == null) {
                            lock = newLock;
                        } else {
                            lock = oldLock;
                        }

                        synchronized (lock) {

                            System.out.println("开始处理图片:" + Thread.currentThread().getName());
//                            if (file.exists()) {
//                                System.out.println("图片存在,直接返回" + Thread.currentThread().getName());
//                                return;
//                            }
//                            GetObjectRequest request = new GetObjectRequest(bucketName, path);
//                            request.setProcess(style);
//                            File fileTemp = new File(
//                                    file.getAbsolutePath() + System.currentTimeMillis() + random.nextInt(10000));
                            // ossClient.getObject(request, file);
//                            fileTemp.renameTo(file);

                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            System.out.println("结束处理图片:" + Thread.currentThread().getName());
                        }

                    }
                }
            }.start();
        }

//        new Thread() {
//            public void run() {
//                while(true) {
//                String hex = null;
//                try {
//                    hex = getFileHex(file);
//                    System.out.println(hex.length());
//                    if (hex.contains("0000000000000000000000000")) {
//                        System.out.println("NG");
//                        System.exit(0);
//                    } else {
//                        System.out.println("OK");
//                    }
//                } catch (IOException e) {
//                    // TODO Auto-generated catch block
//                    e.printStackTrace();
//                }
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//                        // TODO Auto-generated catch block
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }.start();

    }

    public static String getFileHex(File file) throws IOException {
        StringBuilder sb = new StringBuilder();
        byte[] byteArray = FileUtils.readFileToByteArray(file);
        for (byte b : byteArray) {
            int v = b;
            if (v < 0) {
                v = v + 256;
            }
            String hex = Integer.toHexString(v).toUpperCase();
            if (hex.length() == 1) {
                hex = "0" + hex;
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        try {
            OSSUtil2.img();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        new Thread() {
            public void run() {
                while (true) {
                    System.out.println("size:" + fileCache.size());
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            }
        }.start();

        try {
            Thread.sleep(60000 * 5);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        File file = new File("D:\\example-resize.jpg");
        System.out.println("map:" + fileCache.getIfPresent(file.getAbsolutePath()));

    }
}



注意点:
(1)Cache使用expireAfterAccess,一段时间没有访问后才释放。
不要使用expireAfterWrite,这个写入值,到时间就会释放,会导致同步锁失效。

(2)使用fileCache.asMap().putIfAbsent(key, newLock)来处理并发写入。

(3)google Cache处理过期值,不是单独线程处理的,是后面访问时,顺带处理的。
如果一直没有请求,也就不会删掉失效的key
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved