zoukankan      html  css  js  c++  java
  • 线程不安全类

    1.StringBuilder 线程不安全,StringBuffer线程安全
    原因:StringBuffer几乎所有的方法都加了synchronized关键字

    /**
    *  由于StringBuffer 加了 synchronized 所以性能会下降很多
    * 所以在堆栈封闭等线程安全的环境下应该首先选用StringBuilder
    */
    @Override
        public synchronized StringBuffer append(Object obj) {
            toStringCache = null;
            super.append(String.valueOf(obj));
            return this;
        }
    package com.mmall.concurrency.example.commonUnsafe;
    
    import com.mmall.concurrency.annoations.NotThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    
    @Slf4j
    @NotThreadSafe
    public class StringExample1 {
    
        // 请求总数
        public static int clientTotal = 5000;
    
        // 同时并发执行的线程数
        public static int threadTotal = 200;
    
        public static StringBuilder stringBuilder = new StringBuilder();
    
        public static void main(String[] args) throws Exception {
            ExecutorService executorService = Executors.newCachedThreadPool();
            final Semaphore semaphore = new Semaphore(threadTotal);
            final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
            for (int i = 0; i < clientTotal ; i++) {
                executorService.execute(() -> {
                    try {
                        semaphore.acquire();
                        update();
                        semaphore.release();
                    } catch (Exception e) {
                        log.error("exception", e);
                    }
                    countDownLatch.countDown();
                });
            }
            countDownLatch.await();
            executorService.shutdown();
            log.info("size:{}", stringBuilder.length());
        }
    
        private static void update() {
            stringBuilder.append("1");
        }
    }
    View Code
    package com.mmall.concurrency.example.commonUnsafe;
    
    import com.mmall.concurrency.annoations.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    
    @Slf4j
    @ThreadSafe
    public class StringExample2 {
    
        // 请求总数
        public static int clientTotal = 5000;
    
        // 同时并发执行的线程数
        public static int threadTotal = 200;
    
        public static StringBuffer stringBuffer = new StringBuffer();
    
        public static void main(String[] args) throws Exception {
            ExecutorService executorService = Executors.newCachedThreadPool();
            final Semaphore semaphore = new Semaphore(threadTotal);
            final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
            for (int i = 0; i < clientTotal ; i++) {
                executorService.execute(() -> {
                    try {
                        semaphore.acquire();
                        update();
                        semaphore.release();
                    } catch (Exception e) {
                        log.error("exception", e);
                    }
                    countDownLatch.countDown();
                });
            }
            countDownLatch.await();
            executorService.shutdown();
            log.info("size:{}", stringBuffer.length());
        }
    
        private static void update() {
            stringBuffer.append("1");
        }
    }
    View Code

    2.SimpleDateFormat
    SimpleDateFormat 在多线程共享使用的时候回抛出转换异常,应该采用堆栈封闭在每次调用方法的时候在方法里创建一个SimpleDateFormat

    package com.mmall.concurrency.example.commonUnsafe;
    
    import com.mmall.concurrency.annoations.NotThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.text.SimpleDateFormat;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    
    @Slf4j
    @NotThreadSafe
    public class DateFormatExample1 {
    
        private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
    
        // 请求总数
        public static int clientTotal = 5000;
    
        // 同时并发执行的线程数
        public static int threadTotal = 200;
    
        public static void main(String[] args) throws Exception {
            ExecutorService executorService = Executors.newCachedThreadPool();
            final Semaphore semaphore = new Semaphore(threadTotal);
            final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
            for (int i = 0; i < clientTotal ; i++) {
                executorService.execute(() -> {
                    try {
                        semaphore.acquire();
                        update();
                        semaphore.release();
                    } catch (Exception e) {
                        log.error("exception", e);
                    }
                    countDownLatch.countDown();
                });
            }
            countDownLatch.await();
            executorService.shutdown();
        }
    
        private static void update() {
            try {
                simpleDateFormat.parse("20180208");
            } catch (Exception e) {
                log.error("parse exception", e);
            }
        }
    }
    View Code

    这样会抛异常,采用堆栈封闭。

    package com.mmall.concurrency.example.commonUnsafe;
    
    import com.mmall.concurrency.annoations.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    
    import java.text.SimpleDateFormat;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    
    @Slf4j
    @ThreadSafe
    public class DateFormatExample2 {
    
        // 请求总数
        public static int clientTotal = 5000;
    
        // 同时并发执行的线程数
        public static int threadTotal = 200;
    
        public static void main(String[] args) throws Exception {
            ExecutorService executorService = Executors.newCachedThreadPool();
            final Semaphore semaphore = new Semaphore(threadTotal);
            final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
            for (int i = 0; i < clientTotal ; i++) {
                executorService.execute(() -> {
                    try {
                        semaphore.acquire();
                        update();
                        semaphore.release();
                    } catch (Exception e) {
                        log.error("exception", e);
                    }
                    countDownLatch.countDown();
                });
            }
            countDownLatch.await();
            executorService.shutdown();
        }
    
        private static void update() {
            try {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
                simpleDateFormat.parse("20180208");
            } catch (Exception e) {
                log.error("parse exception", e);
            }
        }
    }
    View Code

    另一种方式是使用joda-time的DateTimeFormatter(推荐使用)

    <dependency>
               <groupId>joda-time</groupId>
               <artifactId>joda-time</artifactId>
               <version>2.9</version>
     </dependency>
    package com.mmall.concurrency.example.commonUnsafe;
    
    import com.mmall.concurrency.annoations.ThreadSafe;
    import lombok.extern.slf4j.Slf4j;
    import org.joda.time.DateTime;
    import org.joda.time.format.DateTimeFormat;
    import org.joda.time.format.DateTimeFormatter;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    
    @Slf4j
    @ThreadSafe
    public class DateFormatExample3 {
    
        // 请求总数
        public static int clientTotal = 5000;
    
        // 同时并发执行的线程数
        public static int threadTotal = 200;
    
        private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyyMMdd");
    
        public static void main(String[] args) throws Exception {
            ExecutorService executorService = Executors.newCachedThreadPool();
            final Semaphore semaphore = new Semaphore(threadTotal);
            final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
            for (int i = 0; i < clientTotal; i++) {
                final int count = i;
                executorService.execute(() -> {
                    try {
                        semaphore.acquire();
                        update(count);
                        semaphore.release();
                    } catch (Exception e) {
                        log.error("exception", e);
                    }
                    countDownLatch.countDown();
                });
            }
            countDownLatch.await();
            executorService.shutdown();
        }
    
        private static void update(int i) {
            log.info("{}, {}", i, DateTime.parse("20180208", dateTimeFormatter).toDate());
        }
    }
    View Code

    3.ArrayList,HashMap,HashSet等Collections

    4.先检查再执行

    // 非原子性
    if(condition(a)){
      handle(a);
    }
  • 相关阅读:
    CentOS 7.3 CDH 5.10.0 Druid0.12.4安装记录
    cloudera manager卸载流程
    CDH5.10.0 离线安装(共3节点) 转
    CentOS 7 安装Httpd(转)
    CentOS下MySQL的彻底卸载
    CentOS7 修改主机名
    sendEvent()
    QSignalMapper Class
    ubuntu12.04开启虚拟机的unity模式
    BCM_I2C函数更改
  • 原文地址:https://www.cnblogs.com/xiangkejin/p/9268892.html
Copyright © 2011-2022 走看看