JDK并发相关并发包

synchronized的功能扩展:

重入锁;ReentrantLock;

其实也就是lock对于synchronized的替代了,要注意的一个点就是你可以锁多个,但是你锁了几个,最后就要解锁几个这个问题;

使用lock.lock()加锁,使用lock.unlock()解锁;

提供中断处理;

  使用中断锁,线程可以被中断,也就是说,当一个线程正在等待锁的时候,他依然可以收到一个通知,被告知无须等待,可以停止工作了,使用的是lock.lockInterruptibly();方法;

锁申请等待限时;

  给锁给定一个时间,如果超过了这个时间的话,就让线程自动放弃;使用的是lock.trylock(时间段,时间单位);另外还有一个就是lock.trylock();如果是带参数的,就是最多等待这么多时间,超过了时间就返回false,成功获得了锁,就返回true;如果是不带参数直接运行,就是比较直接的,如果锁未被占用,则申请锁成功,返回true,否则就是失败了,直接返回false;

    公平锁;

公平锁的一个特点就是:它不会产生饥饿现象;所有的锁都是先到先等,不得插队;但是维持公平需要一个有序队列,实现成本较高,性能相对也非常低下,默认情况下,锁是非公平的;

以下是我们整理的几个重要方法:

1,lock():获得锁,如果锁已经被占用,则等待;

2,lockInterruptibly():获得锁,但优先响应中断;

3,tryLock():尝试获得锁,如果成功,返回true,失败返回false,该方法不等待,立即返回;

4,tryLock(Long time,TimeUnit unit):在给定的时间内尝试获得锁;

5,unlock():释放锁;

重入锁的好搭档:Condition条件;

使用new Condition可以生成与当前重入锁绑定的Condition实例;使得我们可以让线程在合适的时间等待,或者在某一特定的时刻得到通知,继续执行;

1,await();让当前线程等待,同时释放当前锁,作用上和wait()相似;

2,awaitUninterruptibly();与await()方法基本相同,不会在等待过程中响应中断;

3,singal();用于唤醒一个在等待中的线程,相对的singalAll()方法会唤醒所有在等待中的线程,和notify()类似;

允许多个线程同时访问:信号量;

只允许一个线程访问一个资源,而信号量则可以指定多个线程;

public Semaphore(int permits)

public Semaphore(int permits,boolean fair);第二个参数可以指定是否公平锁;

这所谓的信号量,其实就是一个执行器啦,只是换了名字看不出来了而已。。。参数可以指定有多少个线程;

ReadWriteLock读写锁;

关于读写的问题,我们要明确的一点就是,我们可以对一个文件多次重复读取,但是当读与写发生冲突的时候,我们要做的就是保证他们的互斥了;

读读不互斥;

读写互斥;

写写互斥;

如果读的操作远远大于写的操作的话,读写锁就会发挥最大的功效;

Lock readLock = readWriteLock.readLock();

Lock writeLock = readWriteLock.writeLock();

读线程完全并行,而写会阻塞读;

    倒计时器:CountDownLatch;

此工具通常用来控制线程等待,让某一个线程等待知道倒计时结束,再开始执行;

只有当你一开始设定的所有线程都跑完了,你这个倒计时器才算真正结束了;

CountDownLatch end = new CountDownLatch(10);

end.countDown();

当调用CountDownLatch.countDown()方法的时候,也就是通知CountDownLatch,一个线程已经完成了任务,倒计时器可以减1了;

    循环珊栏;CyclicBarrier;

另外一种多线程并发控制实用工具;

其实本质上跟倒计时器是差不多的功能类似,唯一的区别就在于可以反复使用,而且可以设置,当计数结束之后,系统下一步要执行的动作;

public CyclicBarrier(int parties,Runnable barrierAction);

其中barrierAction是执行的动作;

线程阻塞工具类:LockSupport;

可以在线程内任意位置让线程阻塞;和Thread.suspend()相比,弥补了由于resume()在前发生,导致线程无法继续执行的情况;

与object.wait()相比,不需要先获得某个对象的锁,也不会抛出interruptedException异常;

LockSupport.park();

LockSupport.unpark(t1);

除了有定时阻塞的功能外,LockSupport.park()还能支持中断影响;但是LockSuppor.park()不会抛出InterruptedException异常,他只是默默的返回;

也就是说:LockSupport.park()进行阻塞之后,如果中断这个线程,不会抛出异常,而是默默的返回;

线程复用:线程池;

我们在这里用到了池的概念来保存管理我们的线程;

当我们要使用线程的时候,不是创建,而是从池子中去取,当我们要关闭线程的时候,是将这个线程返回给池子,方便其他人使用;

JDK对线程池的支持;

newFixedThreadPool(int nThreads);

newSingleThreadExecutor();

newCachedThreadTool();

newSingleThreadScheduledExector();

newScheduledThreadPool(int corePoolSize);

newFixedThreadPool():该方法返回一个固定线程数量的线程池;线程池的数量保持不变,若线程池已满,新的任务会被暂存在一个任务队列中;

newSingleThreadExecutor();该线程池只有一个线程在里面,多余任务会被保存到一个任务队列中;

newCachedThreadPool();返回一个根据实际情况调整线程数量的线程池,也就是说,这个线程池中的线程是可以可调整的。当所有的线程都在工作而此时又有新的任务提交,则会扩展线程的数量;

newSingleThreadScheduledExecutor();返回一个ScheduledExecutorService对象,在ExecutorService接口上扩展了在给定时间执行某任务的功能,

newScheduledThreadPool()方法,可以指定线程数量和时间的线程池;

核心线程池的内部实现;

都是在原有的ThreadPoolExecutor()的基础上进行的参数设置和修改;

而其实,这个ThreadPoolExecutor()内部的参数也有很多的;

int corePoolSize;线程池中线程的数量;

int maximumPoolSize;指定了线程池的最大线程数量;

long keepAliveTime;当线程池数量超过了corePoolSize时吗,多与的空闲线程的存活时间;

TimeUnit unit;keepAliveTime的时间单位;

BlockingQueue<Runnable> workQueue:任务队列,被提交但尚未被执行的任务;

ThreadFactory threadFactory;线程工厂,用于创建线程,一般用默认的;

handler;拒绝策略,当任务太多来不及处理,如何拒绝任务;

现在我们上面的几个线程池是如何通过ThreadPoolExecutor()以及内部的参数来设定的呢,我们现在就来说一下;

其中newFixedThreadPool(nThreads,nThreads,0L,new LinkedBlockingQueue<Runnable>);

newSingleThreadExecutor(1,1,0L,new LinkedBlockingQueue<Runnable>);

newCachedThreadPool(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());

其中,我们可以看出,当newCachedThreadPool时,我们是指定线程池数量为0,但是最大线程数为无限,而且采用的任务队列跟上面的队列不一样,下面将重点说明这两种任务队列的不同之处;

SynchronousQueue:这是直接提交的队列,每一个线程都会直接提交,不会真实地保存,而是直接将新任务交给线程执行器;

ArrayBlockingQueue:这是有界的任务队列,需要带一个参数,表示该队列的最大容量;

LinkedBlockingQueue:这是无界的任务队列,多余的任务会先放到这里;

PriorityBlockingQueue:这是优先任务队列,根据任务自身的优先级顺序先后执行;

不要重复发明轮子:JDK的并发容器;

ConcurrentHashMap:高效的并发HashMap;

CopyOnWriteArrayList:在读多写少的场合,这个List的性能非常好,远远好于Vector(另外。。Vector已经过时了,不用了);

ConcurrentLinkedQueue:高效的并发队列,使用链表实现,可以看做一个线程安全的LinkedList;

BlockingQueue:表示阻塞队列,详情可以查看一下生产者——消费者模式;

ConcurrentSkipListMap:跳表的实现;这是一个Map,使用跳表的数据结构进行快速查找;

以上并发容器的内部数据结构实现,我们在下一章会提到;敬请期待!

原文地址:https://www.cnblogs.com/zxx123/p/9736046.html

时间: 2024-10-19 08:05:32

JDK并发相关并发包的相关文章

今天学了点并发相关的知识

Java并发相关知识集锦 1.class文件 class文件包含JAVA程序执行的字节码:数据严格按照格式(虚拟机要求的一种规范)紧凑排列在class文件中的二进制流,中间无任何分隔符:文件开头有一个0xcafebabe(16进制)特殊的一个标志. 这类文件专门给JVM读里面的内容,因此具有很复杂的格式,程序员阅读可以进行工具查看. 1.1查看class文件内容 Demo1.class的内容如下: public class Demo1 { public static void main(Stri

JDK并发工具包CompletionService和ExecutorCompletionService的好处和使用场景

<Java并发编程实践>一书6.3.5节CompletionService:Executor和BlockingQueue,有这样一段话: "如果向Executor提交了一组计算任务,并且希望在计算完成后获得结果,那么可以保留与每个任务关联的Future,然后反复使用get方法,同时将参数timeout指定为0,从而通过轮询来判断任务是否完成.这种方法虽然可行,但却有些繁琐.幸运的是,还有一种更好的方法:完成服务CompletionService." 这是什么意思呢?我们通过

JDK并发工具类

在JDK的并发包里提供了几个非常有用的并发工具类.CountDownLatch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程间交换数据的一种手段. 1等待多线程完成的CountDownLatch CountDownLatch:CountDownLatch允许一个或多个线程等待其他线程完成操作.与thread.join方法类似但功能更多.该计数器只能使用一次 CountDownLatch的构造函数接收一个int类型的参数作

java并发相关内容

1. vilatile,锁和原子操作 这三个是理解java并发的基础. 简单来说,vilatile修饰的变量,可以保证对其的改变所有线程可见,这个机制实际上也是依赖原子操作的: 锁,主要分为偏向锁,轻量级锁和重量级锁:资源消耗也是越来越大的.使用java的synchronized的关键字或者新的锁用法,都是在这三种锁中做选择,jdk6之后默认优先使用偏向锁,也可以通过UseBaisedLocking=false关闭偏向锁.使用偏向锁的依据,一个是客观事实,通常都是同一个线程获取锁:另一个也是考量

Java中涉及线程和并发相关的内容

1:线程池 与每次需要时都创建线程相比,线程池可以降低创建线程的开销,这也是因为线程池在线程执行结束后进行的是回收操作,而不是真正的 销毁线程. 2:ReentrantLock ReentrantLock提供了tryLock方法,tryLock调用的时候,如果锁被其他线程持有,那么tryLock会立即返回,返回结果为false,如果锁没有被 其他线程持有,那么当前调用线程会持有锁,并且tryLock返回的结果是true, lock.lock(); try { //do something } f

java_guide_9-30_并发相关

3.1 CopyOnWriteArrayList 简介 public class CopyOnWriteArrayList<E> extends Object implements List<E>, RandomAccess, Cloneable, Serializable 在很多应用场景中,读操作可能会远远大于写操作.由于读操作根本不会修改原有的数据,因此对于每次读取都进行加锁其实是一种资源浪费.我们应该允许多个线程同时访问List的内部数据,毕竟读取操作是安全的. 这和我们之前

Ubuntu下安装JDK以及相关配置

1.查看系统位数,输入以下命令即可 getconf LONG_BIT 2.下载对应的JDK文件,我这里下载的是jdk-8u60-linux-64.tar.gz 3.创建目录作为JDK的安装目录,这里选择安装位置为:/usr/java/ sudo mkdir /usr/java 4.解压文件带/usr/java/目录下,文件下载的位置是在下载目录下的 cd 下载sudo tar zxvf jdk-8u60-linux-x64.tar.gz -C /usr/java/ 5.进入到/usr/java/

JDK并发工具之多线程团队协作:同步控制

一.synchronized的功能扩展:重入锁(java.util.concurrent.locks.ReentrantLock) 重入锁可以完全替代synchronized关键字.在JDK 5.0的早期版本中,重入锁的性能远远好于synchronized,但从JDK 6.0开始,JDK在syn-chronized上做了大量的优化,使得两者的性能差距并不大. 01 public class ReenterLock implements Runnable{ 02 public static Ree

51CTO的无闻的Go基础教程中并发相关的概念有错误

无闻并发的课程看了下,然后给他搞晕了,册那,我是铂金便便啊,脾气是很屎的,你不解释清楚么,我就自己去搞清楚. 无闻说缓冲channel不会阻塞,非缓存channel会阻塞,真的是这样么? 无闻本人举了个例子 func main(){     c:=make(chan bool,1)     go fun(){         fmt.println("GO!")         <-c     }()     c<-true } 上面的代码只要把1去掉就会输出GO!不去掉就