effect java 学习摘要(8) - 并发

同步访问共享的可变数据

  • synchronized : 可以保证在同一时刻,只有一个线程可以执行某一个方法, 或者某一个代码块.

  • 多线程访问, 可能会导致同一对象状态发生变化. 同步 可以使多线程看到由同一个锁保护的之前所有的修改效果.

  • 非long或double类型的变量, 读写操作一个变量是原子的

  • 在线程之间进行可靠的通信, 也为了互斥访问, 同步是必要的.

  • 不要使用 Thread.stop() , 要阻止一个线程妨碍另一个线程 ,正确做法如下 :

    public class StopThread {
    
        public static boolean stopRequested;
    
        private static synchronized void requestStop() {
            stopRequested = true;
        }
    
        public static synchronized boolean stopRequested() {
            return stopRequested;
        }
    
        public void stopThread() throws InterruptedException {
            Thread backgroundThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int i = 0;
                    while (!stopRequested()) {
                        i++;
                    }
                }
            });
            backgroundThread.start();
            TimeUnit.SECONDS.sleep(1);
            requestStop();
        }
    }
    
  • 如果读写操作都没有进行同步 , 那么同步就不会起作用.

    public class StopThread {
    
        public static volatile boolean stopRequested;
    
        public void stopThread() throws InterruptedException {
            Thread backgroundThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int i = 0;
                    while (!stopRequested) {
                        i++;
                    }
                }
            });
            backgroundThread.start();
            TimeUnit.SECONDS.sleep(1);
            stopRequested = true;
        }
    }
    
  • 多个线程共享可变数据的时候, 每个读或者写数据的线程都必须执行同步

避免过度同步

  • 共享数据类型,需要使用线程安全的数据结构 , 例如 : CopyOnWriteArrayList

executor和task优先于线程

  • 尽量避免自己编写工作队列, 尽量不要直接使用线程, 使用java提供的executor线程池

并发工具优先于wait和notify

  • 线程高级工具 :

    • Executor Framework
    • 并发集合
    • 同步器 : CountDownLatch 和 Semaphore
      public class Synchronizer {
      
          final Executor executor = Executors.newSingleThreadExecutor();
          final CountDownLatch ready = new CountDownLatch(3);
          final CountDownLatch start = new CountDownLatch(1);
          final CountDownLatch done = new CountDownLatch(3);
          final Runnable runnable = new Runnable() {
              @Override
              public void run() {
                  //do nothing
              }
          };
      
          private long test() throws InterruptedException {
              for (int i = 0;i < 3; i++) {
                  executor.execute(new Runnable() {
                      @Override
                      public void run() {
                          ready.countDown();
                          try {
                              start.await();
                              runnable.run();
                          } catch (InterruptedException e) {
                              Thread.currentThread().interrupt();
                          } finally {
                              done.countDown();
                          }
      
                      }
                  });
              }
              ready.await();
              long startNanos = System.nanoTime();
              start.countDown();
              done.await();
              return System.nanoTime() - startNanos;
          }
      }
      
  • 调用wait方法,应当用循环之内调用 , 永远不要在循环外调用
  • 优先使用notifyAll , 当只有一个线程被唤醒才使用notify

延迟初始化

  • lazy initializition holder class 模式 : 常见用于单例模式

        private static class FieldHolder {
            static final FieldType field = computeFieldValue();
        }
    
        static FieldType getFieldType() {
            return FieldHolder.field;
        }
    

避免使用线程组

  • ThreadGroup 已经为过时的API, 没必要继续使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值