Welcome to pan’s blog.
- Hi, this is Zhang Pan. I’m documenting my learning notes in this blog.
- Email: payne4handsome@163.com.
Welcome to pan’s blog.
java并发包已经存在Reentrant锁和条件锁,已经可以满足很多并发场景下线程安全的需求。但是在大量读少量写的场景下,并不是最优的选择。与传统锁不同的是读写锁的规则是可以共享读,但只能一个写。很多博客中总结写到读读不互斥,读写互斥,写写互斥。就读写这个场景下来说,如果一个线程获取了写锁,然后再获取读锁(同一个线程)也是可以的。锁降级就是这种情况。但是如果也是同一个线程,先获取读锁,再获取写锁是获取不到的(发生死锁)。所以严谨一点情况如下: 项目 非同一个线程 同一个线程 读读 不互斥 不互斥 读写 互斥 锁升级(不支持),发生死锁 写读 互斥 锁降级(支持),不互斥 写写 互斥 不互斥 读写锁的主要特性: 公平性:支持公平性和非公平性。 重入性:支持重入。读写锁最多支持 65535 个递归写入锁和 65535 个递归读取锁。 锁降级:遵循获取写锁,再获取读锁,最后释放写锁的次序,如此写锁能够降级成为读锁。 ReentrantReadWriteLock java.util.concurrent.locks.ReentrantReadWriteLock ,实现 ReadWriteLock 接口,可重入的读写锁实现类。在它内部,维护了一对相关的锁,一个用于只读操作(共享锁),另一个用于写入操作(排它锁)。 ReentrantReadWriteLock 类的大体结构如下: /** 内部类 读锁 */ private final ReentrantReadWriteLock.ReadLock readerLock; /** 内部类 写锁 */ private final ReentrantReadWriteLock.WriteLock writerLock; final Sync sync; /** 使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock */ public ReentrantReadWriteLock() { this(false); } /** 使用给定的公平策略创建一个新的 ReentrantReadWriteLock */ public ReentrantReadWriteLock(boolean fair) { sync = fair ?...
上一篇 文章中我们分析了ReentrantLock的实现原理,今天在分析一下条件锁。条件锁的具体实现在AbstractQueuedSynchronizer的内部类ConditionObject类中,总之,java中的锁,离不开AQS的实现。条件锁一般如下使用。 class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock....
Java中对线程池提供了很好的支持,有了线程池,我们就不需要自已再去创建线程。如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。JAVA的线程池中的线程可以在执行完任务后,不销毁,继续执行其他的任务。所以了解Java的线程池对我们掌握并发编程是很有帮助的。 先看一下线程池框架Executors涉及到的核心类。 Executor:父类,官方表述为用来解耦任务的提交,可以自已实现,比如调用线程执行该任务,或者起一个新的线程执行该任务 ExecutorService:比父类Executor定义了更多的接口用来提交、管理、终止任务 AbstractExecutorService:提供了ExecutorService默认实现 下面我就从Executors这个多线程框架开始讲起,首先看一下Executors中主要的方法 ThreadPoolExecutor:比AbstractExecutorService提供更多的功能,特别是大量的线程创建,销毁。在性能上更优越。 Executors:工厂类,提供了几个核心创建线程池的方法。 Executors核心方法 public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); } public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit....
java 泛型 很多朋友对java的泛型不是很理解,很多文章写的已不是很清楚,这篇博客对java泛型进行 一个总结。 1.泛型的转换 List foo1 = new ArrayList();//illegal 很多朋友会写出上面的代码,但会报如下错误:Type mismatch: cannot convert from ArrayList to List 尽管Interge是Number的子类,但是ArrayList不是List的子类,所以报错。下图可以很好解释这个问题。 2.java泛型的通配符? 这里可以分为两类(1)? extends T (2) ? super T. 很多朋友对这两个不是很理解,也不知道上面时候用,我们知道java中提供泛型技术,是为了提供安全检查的,使得我们写的代码更加的健壮。 2.1 ? extends T public static void print_e(List<? extends Number> list){ for(Number n : list){ System.out.println(n); } } 上面一个函数,我们可以传递如下的参数 List<Integer> list_i = new ArrayList<Integer>(); for(int i=0;i<10;i++){ list_i.add(i); } List<Double> list_d = new ArrayList<Double>(); for(int i=0;i<10;i++){ list_d.add(i+0.0); } print_e(list_i); print_e(list_d); 使得我们写的代码即具有通用型有可以提供必要的安全检查,当然print_e你可以写出如下形式,这里就不具有安全检查的效果了。 void print_e(List list) 但是经常有的朋友写出如下的代码,我们举一个stackoverflow上的一个例子:...
$开头的变量 测试代码,sh文件名:params.sh #!/bin/bash # $$ Shell本身的PID(ProcessID) printf "The complete list is %s\n" "$$" # $! Shell最后运行的后台Process的PID printf "The complete list is %s\n" "$!" # $? 最后运行的命令的结束代码(返回值) printf "The complete list is %s\n" "$?" # $* 所有参数列表 printf "The complete list is %s\n" "$*" # $@ 所有参数列表 printf "The complete list is %s\n" "$@" # $# 添加到Shell的参数个数 printf "The complete list is %s\n" "$#" # $0 Shell本身的文件名 printf "The complete list is %s\n" "$0" # $1 第一个参数 printf "The complete list is %s\n" "$1" # $2 第二个参数 printf "The complete list is %s\n" "$2 执行命令...