zoukankan      html  css  js  c++  java
  • JAVA 多线程编程之一(基础)

    1.原子变量(java.util.concurrent.atomic)

      原子状态,变化不会被打断,如 AtomicLong , AtomicInteger 

    2.内部锁  synchronized 块

      synchronized方法的锁就是方法所在的对象本身,可重入

    3.共享变量

      Volatile变量,每次从内存取出数据,可以获得最新的副本。

      没有同步情况下的共享变量,可能执行顺序不是按照代码的组织,

      

    public  class NoVisibility{
        private static boolean ready;
        private static int number;
        
         private static class ReaderThread extends Thread{
                public void run(){
                    while(!ready){
                        Thread.yield();
                     }
                    System.out.println(number);
                 } 
          }
    
        public static void main(String args[]){
                new ReaderThread().start();
                number = 42;
                ready =  true;
        }

      栈限制,把本地的引用类型限制在本地线程中,不溢出

      不可变对象永远是线程安全的

    4.ThreadLocal   允许线程和自己的变量保存在一起

      向已有的线程安全类添加功能,

      

    public class BetterVector<E> extends Vector<E>{
        public synchronized boolean putIfAbsent(E x){
            ...
        }
    }

      但是下面这种方式不是线程安全的:

    public class ListHelper<E>{
        public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    
        public synchronized boolean putIfAbsent(E x){
                   ...
        }
    }

    因为synchronized关键字锁住的是 ListHelpder类,所以并没有获得List的锁,那么在putIfAbsent中修改List时,是不能保证

    其它方法不对list修改。

    下面的方法才是正确的:

    public class ListHelper<E>{
        public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    
        public  boolean putIfAbsent(E x){
                synchronized(list);
                   ...
        }
    }

    或者是使用组合实现List接口,这样第一种方式就是正确的,因为获得了正确的锁。

    5. 同步容器

       Java 5.0 提供了并发容器来替换同步容器,提高并发的效率。 ConcurrentHashMap代替SynchronizedMap

       FutureTask 通过Callable 实现,可以理解为是一个可携带结果的Runnable

       semaphore 信号量,控制对资源的访问数量限制

       Barrier  提供一种可以一次执行多个线程,直到所有的线程都完成才继续进行,有任何一个线程没有完成,所有 

                  完成的现成都要等待这个线程完成

      一个正确的多线程访问的缓存的写法

      

    package net.jcip.examples;
    
    import java.util.concurrent.*;
    
    /**
     * Memoizer
     * <p/>
     * Final implementation of Memoizer
     *
     * @author Brian Goetz and Tim Peierls
     */
    public class Memoizer <A, V> implements Computable<A, V> {
        private final ConcurrentMap<A, Future<V>> cache
                = new ConcurrentHashMap<A, Future<V>>();
        private final Computable<A, V> c;
    
        public Memoizer(Computable<A, V> c) {
            this.c = c;
        }
    
        public V compute(final A arg) throws InterruptedException {
            while (true) {
                Future<V> f = cache.get(arg);
                if (f == null) {
                    Callable<V> eval = new Callable<V>() {
                        public V call() throws InterruptedException {
                            return c.compute(arg);
                        }
                    };
                    FutureTask<V> ft = new FutureTask<V>(eval);
                    f = cache.putIfAbsent(arg, ft);
                    if (f == null) {
                        f = ft;
                        ft.run();
                    }
                }
                try {
                    return f.get();
                } catch (CancellationException e) {
                    cache.remove(arg, f);
                } catch (ExecutionException e) {
                    throw LaunderThrowable.launderThrowable(e.getCause());
                }
            }
        }
    }
  • 相关阅读:
    700. Search in a Binary Search Tree
    100. Same Tree
    543. Diameter of Binary Tree
    257. Binary Tree Paths
    572. Subtree of Another Tree
    226. Invert Binary Tree
    104. Maximum Depth of Binary Tree
    1、解决sublime打开文档,出现中文乱码问题
    移植seetafaceengine-master、opencv到ARM板
    ubuntu16.04-交叉编译-SeetaFaceEngine-master
  • 原文地址:https://www.cnblogs.com/zhanglanyun/p/3303675.html
Copyright © 2011-2022 走看看