• 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());
                }
            }
        }
    }
  • 相关阅读:
    [Windows] 使用SC 命令管理与配置服务
    [SharePoint 2010] SharePoint 2010 部署、收回和删除解决方案----STSADM和PowerShell
    [SharePoint 2010] SharePoint 2010 FBA 配置以及自定义首页
    [Log]ASP.NET之HttpModule 事件执行顺序
    [SQL] 命令远程恢复数据库
    [工具] 各种主流 SQLServer 迁移到 MySQL 工具对比
    [工具] TreeSizeFree 查看每个文件夹的大小
    [APP] Android 开发笔记 006-使用短信验证SDK进行短信验证
    [APP] Android 开发笔记 004-Android常用基本控件使用说明
    [APP] Android 开发笔记 003-使用Ant Release 打包与keystore加密说明
  • 原文地址:https://www.cnblogs.com/zhanglanyun/p/3303675.html
Copyright © 2020-2023  润新知