简体   繁体   English

Java:我的方法线程安全吗?

[英]Java : Is my method thread safe?

In class CACallHandler there is a method created by me ie checkCallAllowed . CACallHandler类中,有一个我创建的方法,即checkCallAllowed I have taken everything as ConcurrentHashMap and AtomicInteger. 我把所有内容都当作ConcurrentHashMap和AtomicInteger。

Please ignore the logic of checkCallAllowed but i want to know that if multiple threads will access this method on the same object concurrently, then will it safe. 请忽略checkCallAllowed的逻辑,但我想知道,如果多个线程将同时在同一个对象上访问此方法,那将是安全的。

i dont want to synchronize the entire method as there will be a performce hit. 我不想synchronize整个方法,因为会有性能方面的问题。

Requesting your help. 请求您的帮助。

i have executed this method with 30 threads with and without method synchronized, both are giving same result. 我已经用30个线程执行了此方法,有和没有同步方法,两者给出的结果相同。 So want to understand if there will be 200 threads then it will be safe or not. 因此,想了解是否会有200个线程,那么它是否安全。

public class CACallHandler {

public ThrottleCallAlert throttleCallAlert ;

Map<String, TCACriteria> criteriaMap = new HashMap<String, TCACriteria>();

List<TCAListener> listenerList =  new LinkedList< TCAListener>();
Map<String, AtomicInteger[]> intervalMap = new ConcurrentHashMap<String, AtomicInteger[]>();
Map<String, AtomicInteger> oddMap = new ConcurrentHashMap<String, AtomicInteger>();
Map<String, AtomicInteger> evenMap = new ConcurrentHashMap<String, AtomicInteger>();
Map<String, List<ThrottleAlarmType> > alarmsRaised = new ConcurrentHashMap<String, List<ThrottleAlarmType>>();


public Map<String, AtomicInteger> getCurrentMap(){

    String abc = new SimpleDateFormat("ss").format(new Date());
    if(Integer.parseInt(abc) % 2 == 0){
        // even map 
        return evenMap;
    }else{
        // odd map 
        return oddMap;
    }
}

public String getCriteria(String callingNo, String Origin1, String Origin2){

    String criteriaName = "";
    for (Map.Entry<String, TCACriteria> entry : criteriaMap.entrySet())
    {
        TCACriteria criteria = entry.getValue();
        if( callingNo.equals(criteria.callingNo) || Origin1.equals(criteria.sipOrigin) || Origin2.equals(criteria.inapOrigin)){
            criteriaName =  entry.getKey();
            return criteriaName;
        }
    }
    return criteriaName;
}

public boolean checkCallAllowed(String calling, String Origin1, String Origin2){

    boolean returnFlag = false;

    String currentCriteria = getCriteria(calling, Origin1, Origin2); // test

    if(!currentCriteria.isEmpty()){

        String abc = new SimpleDateFormat("ss").format(new Date());
        if(Integer.parseInt(abc) % 2 == 0){
            //taking odd map based on seconds
            if(oddMap.get(currentCriteria).get() != 0 ){

                for(int i=0; i < intervalMap.get(currentCriteria).length; i++){
                    System.out.println("aaaaa :"+ intervalMap.get(currentCriteria)[i].get());
                    if(intervalMap.get(currentCriteria)[i].get() == -1 ){
                        if(oddMap.get(currentCriteria).get() >= throttleCallAlert.getLwm()){
                            intervalMap.get(currentCriteria)[i].set(oddMap.get(currentCriteria).get());

                        }else{
                            if(alarmsRaised.get(currentCriteria) != null && oddMap.get(currentCriteria).get() < throttleCallAlert.getLwm()){

                                if(alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.MAJOR)){
                                    System.out.println("ALARM cleared-111@@!!---MAJOR-->>>. currentCriteria "+currentCriteria);
                                    listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.MAJOR);
                                    alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(2, ThrottleAlarmType.NONE);
                                }
                            }

                            for(int j=0; j < intervalMap.get(currentCriteria).length; j++){

                                intervalMap.get(currentCriteria)[j] = new AtomicInteger(-1);
                            }
                        }
                        break;
                    }

                    if(i == intervalMap.get(currentCriteria).length - 1){
                        int majorAlarm = 0; 
                        boolean raiseAlarmRequired = true;
                        System.out.println("array not -1 111");
                        for(int j=0; j < intervalMap.get(currentCriteria).length; j++){
                            if(intervalMap.get(currentCriteria)[j].get() < throttleCallAlert.getLwm() ){
                                raiseAlarmRequired = false;
                            }
                            intervalMap.get(currentCriteria)[j] = new AtomicInteger(-1);
                        }

                        if(raiseAlarmRequired){
                            System.out.println("ALARM RAISED--11---->>>. currentCriteria " + currentCriteria);

                            //start
                            if(majorAlarm == intervalMap.get(currentCriteria).length ){ // major 
                                if((alarmsRaised.get(currentCriteria) != null && ! alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.MAJOR))){
                                    returnFlag = false;
                                    alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(2, ThrottleAlarmType.MAJOR);
                                    listenerList.get(0).alarmRaised(currentCriteria, ThrottleAlarmType.MAJOR);

                                }
                            }
                            //end
                        }

                        if(alarmsRaised.get(currentCriteria) != null && oddMap.get(currentCriteria).get() < throttleCallAlert.getLwm()){
                            if(alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.WARNING)){
                                System.out.println("ALARM cleared-111----->>>. currentCriteria "+currentCriteria);
                                listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.WARNING);
                                alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(0, ThrottleAlarmType.NONE);
                            }

                        }
                        intervalMap.get(currentCriteria)[0].set(oddMap.get(currentCriteria).get()); 
                    }

                }
                oddMap.get(currentCriteria).set(0);
            }

            // even map 
            evenMap.get(currentCriteria).incrementAndGet();

        }else{
            // takeing even map same as odd map mentioned above
            }
    }

    return returnFlag;
}

} }

No, your method is not Thread Safe, but your maps are. 不,您的方法不是线程安全的,但是您的映射是。 The fact that its method is not synchronized makes it asynchronous, but access to Maps is Thread Safe, that is, only one thread can access at a time. 它的方法不同步使它成为异步的事实,但是对Maps的访问是线程安全的,也就是说,一次只能访问一个线程。

I analyzed your code but I confess that I could not understand her business logic. 我分析了您的代码,但我承认我无法理解她的业务逻辑。 To improve your performance and make it more secure to threads, I've separated the processing into two methods and made them synchronized. 为了提高性能并使其对线程更安全,我将处理分为两种方法并使它们同步。 I also made some changes to the code which I commented their reasons. 我还对代码做了一些更改,以说明其原因。 My biggest difficulty has been to understand the negotiating part (what values can be processed in competition or not) and what can be affected in it, but I believe you can also try to use synchronized blocks, for example in the currentCriteriaValue variable synchronized (currentCriteriaValue ) {... What could improve was it, I believe that to get better I would have to have the field of negotiation rule. 我最大的困难是了解协商部分(可以在竞争中处理或不处理哪些值)以及其中可能受到的影响,但我相信您也可以尝试使用同步块,例如在currentCriteriaValue变量中已同步(currentCriteriaValue ){...有什么可以改善的,我认为要变得更好,我必须拥有谈判规则领域。

public class CACallHandler {

    //Only one SimpleDateFormat instance is enought to format all dates
    private SimpleDateFormat sdfSS = new SimpleDateFormat("ss");

    public ThrottleCallAlert throttleCallAlert;

    List<TCAListener> listenerList =  new LinkedList< TCAListener>();
    Map<String, TCACriteria> criteriaMap = new HashMap<String, TCACriteria>();
    Map<String, AtomicInteger[]> intervalMap = new ConcurrentHashMap<String, AtomicInteger[]>();
    Map<String, AtomicInteger> oddMap = new ConcurrentHashMap<String, AtomicInteger>();
    Map<String, AtomicInteger> evenMap = new ConcurrentHashMap<String, AtomicInteger>();
    Map<String, List<ThrottleAlarmType> > alarmsRaised = new ConcurrentHashMap<String, List<ThrottleAlarmType>>();
    static String[] testeValues = {"callingNo", "sipOrigin", "inapOrigin", "A", "B", "C"};


    {//Populates values to test

        throttleCallAlert = new ThrottleCallAlert();

        criteriaMap.put("callingNo", new TCACriteria());
        criteriaMap.put("sipOrigin", new TCACriteria());
        criteriaMap.put("inapOrigin", new TCACriteria());

        evenMap.put("callingNo", new AtomicInteger(1));
        evenMap.put("sipOrigin", new AtomicInteger(2));
        evenMap.put("inapOrigin", new AtomicInteger(3));

        oddMap.put("callingNo", new AtomicInteger(1));
        oddMap.put("sipOrigin", new AtomicInteger(2));
        oddMap.put("inapOrigin", new AtomicInteger(3));

        intervalMap.put("callingNo", new AtomicInteger[] { new AtomicInteger(1), new AtomicInteger(2), new AtomicInteger(3) });
        intervalMap.put("sipOrigin", new AtomicInteger[] { new AtomicInteger(1), new AtomicInteger(2), new AtomicInteger(3) });
        intervalMap.put("inapOrigin", new AtomicInteger[] { new AtomicInteger(1), new AtomicInteger(2), new AtomicInteger(3) });
    }


    public static void main(String[] args) throws InterruptedException {
        CACallHandler handler = new CACallHandler();
        int threads = 10000;
        ExecutorService taskExecutor = Executors.newFixedThreadPool( threads );
        //Thread.sleep(12000);
        Date startTime = new Date();
        for( int i = 0 ; i < threads; i++ ) {
            int i1 = ThreadLocalRandom.current().nextInt(0, 5 + 1);
            int i2 = ThreadLocalRandom.current().nextInt(0, 5 + 1);
            int i3 = ThreadLocalRandom.current().nextInt(0, 5 + 1);
            taskExecutor.execute( new Thread(){ public void run() {handler.checkCallAllowed(testeValues[i1], testeValues[i2], testeValues[i3]);} }  );
        }
        taskExecutor.shutdown();
        taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        Date finishTime = new Date();
        System.out.println( "Execution time in ms: " + (finishTime.getTime() - startTime.getTime()) );

    }



    /**
     * Return the odd or even map based on current time
     * @return Map 
     */
    public Map<String, AtomicInteger> getCurrentMap(){
        switch( getCurrentMapType() ) {
            case EVEN: return evenMap;
            case ODD: return oddMap;
            default: return null;
        }
    }

    /**
     * Check if criteriaMap has the [callingNo | Origin1 | Origin2] passed 
     * @param callingNo - 
     * @param Origin1
     * @param Origin2
     * @return String - the criteriaMap key equals to parameter or empty string
     */
    public String getCriteria(String callingNo, String Origin1, String Origin2){
        for (Map.Entry<String, TCACriteria> entry : criteriaMap.entrySet()){
            TCACriteria criteria = entry.getValue();
            if( callingNo.equals(criteria.callingNo) || Origin1.equals(criteria.sipOrigin) || Origin2.equals(criteria.inapOrigin))
                return entry.getKey();
        }
        return null;
    }

    /**
     * get odd map type based on seconds
     * @return MapType
     */
    private MapType getCurrentMapType() {
        return MapType.EVEN;//No odd implementation
        /*if(Integer.parseInt( sdfSS.format(new Date()) ) % 2 == 0){
            return MapType.EVEN;
        }else{
            return MapType.ODD;
        }*/     
    }

    /**
     * Get the currente criteria based on parameters then process it
     * @param calling
     * @param Origin1
     * @param Origin2
     * @return
     */
    public boolean checkCallAllowed(String calling, String Origin1, String Origin2){
        String currentCriteria = getCriteria(calling, Origin1, Origin2);
        if( currentCriteria != null ){
            switch( getCurrentMapType() ) {
                case EVEN: return proccessEvenMapType(currentCriteria);
                case ODD: return proccessOddMapType(currentCriteria);
                default: return false; //TODO check it
            }
        }
        return false;
    }

    /**
     * Process currentcriteria based on even Map
     * @param currentCriteria
     * @return boolean - always false??
     */
    private synchronized boolean proccessEvenMapType( String currentCriteria ) {
        boolean returnFlag = false; //TODO this variable never receivs true..??
        //Only one call to map, reduce the time on searching and processing
        Integer currentCriteriaValue = oddMap.get(currentCriteria).get();
            if(currentCriteriaValue != 0 ){
                //Only one call to map, reduce the time on searching and processing 
                AtomicInteger[] intervalArray = intervalMap.get(currentCriteria);
                for(int intervalIndex=0; intervalIndex < intervalArray.length; intervalIndex++){
                    AtomicInteger currentInterval = intervalArray[intervalIndex];
                    System.out.println("aaaaa :"+ currentInterval.get());
                    if(currentInterval.get() == -1 ){
                        if(currentCriteriaValue >= throttleCallAlert.getLwm()){
                            currentInterval.set(currentCriteriaValue);
                        }else{
                            List<ThrottleAlarmType> alarmTypeList = alarmsRaised.get(currentCriteria) ; 
                            if(alarmTypeList != null && currentCriteriaValue < throttleCallAlert.getLwm()){
                                if(alarmTypeList.contains(ThrottleAlarmType.MAJOR)){
                                    System.out.println("ALARM cleared-111@@!!---MAJOR-->>>. currentCriteria "+currentCriteria);
                                    listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.MAJOR);
                                    alarmsRaised.put(currentCriteria, alarmTypeList).set(2, ThrottleAlarmType.NONE);
                                }
                            }
                            for(int j=0; j < intervalArray.length; j++){
                                intervalArray[j] = new AtomicInteger(-1);
                            }
                        }
                        break;
                    }

                    if(intervalIndex == intervalArray.length - 1){
                        int majorAlarm = 0; 
                        boolean raiseAlarmRequired = true;
                        System.out.println("array not -1 111");
                        for(int j=0; j < intervalArray.length; j++){
                            if(intervalArray[j].get() < throttleCallAlert.getLwm() ){
                                raiseAlarmRequired = false;
                            }
                            intervalArray[j] = new AtomicInteger(-1);
                        }

                        if(raiseAlarmRequired){
                            System.out.println("ALARM RAISED--11---->>>. currentCriteria " + currentCriteria);
                            //start
                            if(majorAlarm == intervalArray.length ){ // major 
                                if((alarmsRaised.get(currentCriteria) != null && ! alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.MAJOR))){
                                    returnFlag = false;
                                    alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(2, ThrottleAlarmType.MAJOR);
                                    listenerList.get(0).alarmRaised(currentCriteria, ThrottleAlarmType.MAJOR);
                                }
                            }
                            //end
                        }

                        if(alarmsRaised.get(currentCriteria) != null && currentCriteriaValue < throttleCallAlert.getLwm()){
                            if(alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.WARNING)){
                                System.out.println("ALARM cleared-111----->>>. currentCriteria "+currentCriteria);
                                listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.WARNING);
                                alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(0, ThrottleAlarmType.NONE);
                            }
                        }
                        intervalArray[0].set(currentCriteriaValue); 
                    }

                }
                oddMap.get(currentCriteria).set(0);
            }
        // even map 
        evenMap.get(currentCriteria).incrementAndGet();
        return returnFlag;
    }

    private boolean proccessOddMapType( String currentCriteria ) {
        System.out.println("proccessOddMapType Not implemented yet!!");
        return false;
    }

}

enum MapType{
    ODD, EVEN;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM