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
  • 相关阅读:
    libv4l 库【转】
    Leap Motion颠覆操控体验的超精致手势追踪技术【转】
    嵌入式Linux下Camera编程--V4L2【转】
    C语言高级应用---操作linux下V4L2摄像头应用程序【转】
    通过摄像头设备采集一帧数据的例子程序(完整版)【转】
    V4L2 camera 驱动 capture测试程序【转】
    v4l2 spec 中文 Ch01【转】
    Video for Linux Two API Specification Revision 2.6.32【转】
    Video for Linux Two API Specification revision0.24【转】
    OpenCV实践之路——人脸检测(C++/Python) 【转】
  • 原文地址:https://www.cnblogs.com/handsomecui/p/9235430.html
Copyright © 2011-2022 走看看