zoukankan      html  css  js  c++  java
  • 并发问题解决小结

    关于一次自动转单出现的并发问题的解决:

    1.方案:直接用synchronized(customerId),
    存在问题:可能存在坑,字符串的hashCode相同时地址不一定相同,详情见博客:https://blog.csdn.net/u014653197/article/details/76177277
    详见代码:
    package autoTransfer;
    
    import java.util.Scanner;
    
    /**
     * Created by cuijunyong on 2018/6/27.
     */
    public class TestMain {
      private static AutoTransfer autoTransfer = new AutoTransfer();
      private static Scanner cin = new Scanner(System.in);
      public static void main(String[] args) {
    //    String a = cin.next();
    //    String b = cin.next();
    //    String c = cin.next();
    
        new MyThread("123").start();
        new MyThread("123").start();
        new MyThread(new String("123")).start();
    
      }
    
    
    }
    
    class MyThread extends Thread{
    
      private String customerId;
      private static AutoTransfer autoTransfer = new AutoTransfer();
      @Override
      public void run() {
        try {
          autoTransfer.run(customerId);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
      public MyThread(String customerId) {
        this.customerId = customerId;
      }
    }
    View Code
    package autoTransfer;
    
    /**
     * Created by cuijunyong on 2018/6/27.
     */
    public class AutoTransfer{
    
      public void run(String customerId) throws Exception{
        synchronized (customerId){
          System.out.println(Thread.currentThread() + "自动转单开始customerId=" + customerId + " hashCode=" + customerId.hashCode() + "真正内存地址=" + System.identityHashCode(customerId));
          Thread.sleep(5000);
          System.out.println(Thread.currentThread() + "自动转单结束customerId=" + customerId + " hashCode=" + customerId.hashCode() + "真正内存地址=" + System.identityHashCode(customerId));
        }
      }
    
    }
    View Code

    这个简单一点的解决方案可以直接synchronized(customerId.intern())

    2.方案:用concurrentHashMap 进入用map.put(customerId)的返回值判断是否存在,如果返回值不为空,证明已经有customerId在访问,就不执行方法。方法结束时remove掉
    存在问题:如果中途抛出异常会不会造成这一cuntomerId一直不会被remove掉。
    3.方案:添加try{
        if(map.put(customerId)!=null)return;
        Dosomething();
    }catch(){
    }
    finally{
        map.remove(customerId);
    }finally内remove掉
    存在问题:map.put(customerId)放在了try里,会造成并发访问return掉的也执行了finally方法,下次并行就还会造成并发问题。
    4.方案:于是将if(map.put(customerId)!=null)return;放到try外边
    存在问题:出现异常不能被抛出去,前端获取不到异常。
    5.解决方案:不用catch了直接try{}finally{} 
    package autoTransfer;
    
    import java.util.Scanner;
    
    /**
     * Created by cuijunyong on 2018/6/27.
     */
    public class TestMain {
      private static AutoTransfer autoTransfer = new AutoTransfer();
      private static Scanner cin = new Scanner(System.in);
      public static void main(String[] args) {
    //    String a = cin.next();
    //    String b = cin.next();
    //    String c = cin.next();
    
        new MyThread("123").start();
        new MyThread("123").start();
        new MyThread(new String("123")).start();
    
      }
    
    
    }
    
    class MyThread extends Thread{
    
      private String customerId;
      private static AutoTransfer autoTransfer = new AutoTransfer();
      @Override
      public void run() {
        try {
          autoTransfer.run(customerId);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
      public MyThread(String customerId) {
        this.customerId = customerId;
      }
    }
    View Code
    package autoTransfer;
    
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * Created by cuijunyong on 2018/6/27.
     */
    public class AutoTransfer{
    
      private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
      public void run(String customerId) throws Exception{
        if(map.put(customerId, 1) != null){
          return;
        }
        try {
          System.out.println(Thread.currentThread() + "自动转单开始customerId=" + customerId + " hashCode=" + customerId.hashCode() + "真正内存地址=" + System.identityHashCode(customerId));
          Thread.sleep(5000);
          System.out.println(Thread.currentThread() + "自动转单结束customerId=" + customerId + " hashCode=" + customerId.hashCode() + "真正内存地址=" + System.identityHashCode(customerId));
        }finally {
          map.remove(customerId);
        }
    
      }
    
    }
    View Code
  • 相关阅读:
    update数据从一个表到另外一个表中
    数据泵导出
    导入库
    看函数
    导库中的一个表
    一个表的字段存在或者不存在另一表里
    语句2
    语句
    word 内容被锁定,无法修改
    gridview自带分页
  • 原文地址:https://www.cnblogs.com/handsomecui/p/9235430.html
Copyright © 2011-2022 走看看