在班级CACallHandler
中,我创建了一种方法,即checkCallAllowed
。我把所有内容都当作ConcurrentHashMap和AtomicInteger。
请忽略checkCallAllowed
的逻辑,但我想知道如果多个线程同时在同一个对象上访问此方法,那么它是否安全。
我不希望synchronize
整个方法,因为会有一个表演命中。
请求你的帮助。
我已经使用30个线程执行此方法,并且没有方法同步,两者都给出相同的结果。所以想要了解是否会有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;
}
}
答案 0 :(得分:0)
不,你的方法不是线程安全的,但你的地图是。 它的方法不同步这一事实使它异步,但对Maps的访问是线程安全的,也就是说,一次只能访问一个线程。
我分析了你的代码,但我承认我无法理解她的业务逻辑。为了提高性能并使其对线程更安全,我将处理分为两种方法并使它们同步。我还对代码进行了一些更改,我对其原因进行了评论。 我最大的困难是理解谈判部分(可以在竞争中处理哪些值)以及可以在其中受到影响的内容,但我相信您也可以尝试使用synchronized块,例如在currentCriteriaValue变量synchronized(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;
}