[多线程——通过字符串内容来同步]

1. 样例1

public class SycString {

    public static void sys(String str) throws InterruptedException {
        synchronized (str) {
            System.out.println(str);
            TimeUnit.SECONDS.sleep(5);
        }
    }
    
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(10);
        
        Interner pool = Interners.newWeakInterner();
        for(int i = 0; i < 5;i++) {
            es.execute(()->{try {
                SycString.sys(pool.intern(new String("test")));
            } catch (Exception e) {
                e.printStackTrace();
            }});
        }
    }
}

2.样例2

//类1- SynStringTest
package com.tinygao.thread.synstring;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SynStringTest {

    private final static SynString synStr = new SynString();
    private final static Stopwatch sw = Stopwatch.createStarted();
    private static BiConsumer function = (x, y)->{
        synchronized (x.getStringLock(y)) {
            log.info("Get lock: {}", y);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    public static void main(String[] args) throws InterruptedException {
        final ExecutorService executorService = Executors.newFixedThreadPool(
                4,
                new ThreadFactoryBuilder().setNameFormat("SynString-%d").build()
        );
        
        executorService.submit(()->{
            doTask("test");
        });
        executorService.submit(()->{
            doTask("test");
        });
        executorService.submit(()->{
            doTask("test1");
        });
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.DAYS);
        sw.stop();
    }
    
    private static void doTask(String lockStr) {
        function.accept(synStr, lockStr);
        log.info("Do get lockStr successed waste time elapsed : {} ms", sw.elapsed(TimeUnit.MILLISECONDS));
    }
}

//类2- SynString 
package com.tinygao.thread.synstring;
import java.util.concurrent.ConcurrentMap;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SynString {

    private static ConcurrentMap parMap =  Maps.newConcurrentMap();
    
    public  Object getStringLock(String string) {
        Object lock = this;
        if(parMap != null) {
            Object newLock = new Object();
            lock = parMap.putIfAbsent(string, newLock);
            if(lock == null) {
                lock = newLock;
            }
        }
        return lock;
    }
    
    public static void main(String[] args) {
        Object result = parMap.putIfAbsent("h", "g");
        log.info("Get result: {}", result);
    }
}

#2. 具体应用

private static Interner pool = Interners.newWeakInterner();
//这种在分布式系统中会有问题
public static void copyFileToLocal(String hdfsSrc,String localFile) throws IOException{
synchronized (pool.intern(localFile)) {
Path dstLock = new Path(localFile+".lock");
if(localFs.exists(dstLock)) {
log.warn("CopyFileToLocal the file :{} is lock", localFile);
throw new RuntimeException("CopyFileToLocal the file "+localFile+" is lock");
}

        localFs.createNewFile(dstLock);
        
        try {
            doCopyMeger(hdfsSrc, localFile);
        } finally {
            localFs.delete(dstLock, false);
        }
    }
}

你可能感兴趣的:([多线程——通过字符串内容来同步])