java多线程:jdk并发包的总结(转载)

摘要:
不稳定的VM防止将易失性变量的值放入处理器的寄存器。写入值后,它将从处理器的缓存中清除并写入内存,以便其他线程可以立即看到变量的变化。此外,如果线程被阻塞,则线程需要进入阻塞队列。CopyOnWriteArrayList,线程安全,读取操作期间解锁ArrayList;写入时,复制ArrayList。写入后,指针指向新对象。ArrayBlockQueue是一个基于数组、FIFO和线程安全的集合类。其容量可能有限。

转载地址:http://blog.csdn.net/yangbutao/article/details/8479520

1、java 高并发包所采用的几个机制(CAS,volatile,抽象队列同步)

   CAS(乐观操作),jdk5以前采用synchronized,对共享区域进行同步操作,synchronized是重的操作,在高并发情况下,会引起线程频繁切换;而CAS是一种乐观锁机制,compare and swap,不加锁,而是假设没有冲突去完成,若有冲突会重试(非阻塞)。compare&swap是原子操作,基于CPU的原语操作。

   volatile(变量的可见性),VM阻止volatile变量的值放入处理器的寄存器,在写入值以后会被从处理器的cache中flush掉,写到内存中去,这样其他线程都可以立刻看到该变量的变化。

  AQS,抽象队列同步器(原子性操作状态同步位、有序队列、阻塞唤醒进程)

     获取锁:首先判断当前状态是否允许获取锁,如果是就获取锁,否则就阻塞操作或者获取失败,也就是说如果是独占锁就可能阻塞,如果是共享锁就可能失败。另外如果是阻塞线程,那么线程就需要进入阻塞队列。当状态位允许获取锁时就修改状态,并且如果进了队列就从队列中移除。

    释放锁:这个过程就是修改状态位,如果有线程因为状态位阻塞的话就唤醒队列中的一个或者更多线程。

2、锁相关:

Semaphere,控制某资源同时被访问的个数的类

    在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者

    Semaphore position=new Semaphore(2);  

    position.acquire(); //阻塞,直到等待的当前的个数少于2个

    position.release()

CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 

      CountDownLatch end = new CountDownLatch(10);  

      end.countDown();  10次

      end.wait阻塞直到end.countDown();  10次

CyclicBarrier,一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 

      CyclicBarrier barrier = new CyclicBarrier(3);barrier.await()//三次

ReentrantLock,控制并发资源,功能上等同于synchronize

     ReentrantLock  lock=new ReentrantLock();

      lock.lock();

      lock.unlock  

Condition,在同一个锁的情况下,根据不同的情况执行等待和唤醒动作,类似于object.wait、notify操作

     Condition cond=ReentrantLock.newCondition();

     cond.await();

     cond.signal();  

ReentrantReadWriteLock,

读写锁--ReadWriteLock接口及其实现类ReentrantReadWriteLock

ReentrantReadWriteLock中定义了2个内部 类, ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock, 分别用来代表读取锁和写入锁. ReentrantReadWriteLock对象提供了readLock()和writeLock()方法, 用于获取读取锁和写入锁.

  • 读取锁允许多个reader线程同时持有, 而写入锁最多只能有一个writter线程持有.
  • 读写锁的使用场合: 读取共享数据的频率远大于修改共享数据的频率. 在上述场合下, 使用读写锁控制共享资源的访问, 可以提高并发性能.
  • 如果一个线程已经持有了写入锁, 则可以再持有读写锁. 相反, 如果一个线程已经持有了读取锁, 则在释放该读取锁之前, 不能再持有写入锁.
  • 在多线程环境中,读锁和写锁是相互排斥的,一个lock不可能同时拥有读锁和写锁. 

3、并发容器:

1)非并发包中的集合容器,

Collection
|---List
|--ArryList,Vector(thread safe),Linklist
|--Set
|---HashSet
|---Map
         |----HashMap(数组,每个元素是hashentry,利用哈希,定位对象存储的位置index,便于快速定位对象;hash冲突的解决采用链表结构存储)

|----HashTable(thread safe) 

2)并发包中的线程安全的集合容器

  ConcurrentMap( 线程安全的hashMap),默认16个segment的数组,每个segment中实现就是hashMap了,通过hash定位segment。put 操作是在segment层上加锁的,这样可以减少并发的冲突;读操作大多数情况下无锁操作(仅仅找到的hashentry对应的对象为null时,有锁操 作)。

  CopyOnWriteArrayList,线程安全,读操作时无锁的ArrayList;在写时,copy一个ArrayList,写完成后,指针指向新的对象。

  CopyOnWriteArraySet,基于CopyOnWriteArrayList实现。

  ArrayBlockQueue,基于数组,FIFO,线程安全的集合类,容量可以限制。

4、线程池:

Thread,Runable,

Callable,Future(可携带结果的任务)

Executor

   |---ExecutorService
          |---ThreadpoolExecutor  线程池执行Runnable
 Future    future=ThreadpoolExecutor.submit(Runnable run)
                future.cancel();

Executors,提供创建ThreadpoolExecutor的工厂类,提供几种创建方法

FutureTask,主要用于异步取得执行结果和取消执行任务,Runnable

              Callable callable=new Callable();

              FutureTask task=new FutureTask(callable)

             task.run();

             task.get();

             task.cancel();

    线程中断,interrupt()不会中断正在执行的线程,只是将线程的标志位设置成true。但是如果线程在调用 sleep(),join(),wait()方法时线程被中断,则这些方法会抛出InterruptedException,在catch块中捕获到这个 异常时,线程的中断标志位已经被设置成false了,因此在此catch块中调用 t.isInterrupted(),Thread.interrupted()始终都为false, 而t.isInterrupted与 Thread.interrupted()的区别是API中已经说明很明显了,Thread.interrupted()假如当前的中断标志为true, 则调完后会将中断标志位设置成false 

 有些内容待细化和补充....

免责声明:文章转载自《java多线程:jdk并发包的总结(转载)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇微信小程序反编译解包教程java 抽象类下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux系统编程 —互斥量mutex

互斥量mutex 前文提到,系统中如果存在资源共享,线程间存在竞争,并且没有合理的同步机制的话,会出现数据混乱的现象。为了实现同步机制,Linux中提供了多种方式,其中一种方式为互斥锁mutex(也称之为互斥量)。 互斥量的具体实现方式为:每个线程在对共享资源操作前都尝试先加锁,成功加锁后才可以对共享资源进行读写操作,操作结束后解锁。 互斥量不是为了消除竞...

WPF Dispatcher.BeginInvoke子线程更新UI

在开发WPF应用时出现:”调用线程无法访问此对象,因为另一个线程拥有该对象。“ 是因为UI线程是WPF应用的主线程,若尝试子线程更新UI线程应使用Dispatcher.BeginInvoke()或者Invoke()方法。 Dispatcher.BeginInvoke() //异步执行,不等待委托结束就更新 Dispatcher.Invoke()     ...

跨线程调用控件

vs2005中默认是不允许跨线程调用控件的,否则会出错。但是也有解决办法: 以下内容为转贴 在VS 2005  中考虑到线程的安全性,不允许跨线程调用控件!  为了解决这一问题   1. 将Control 的 CheckForIllegalCrossThreadCalls 属性设置为假, 不去捕获错误线程的调用,但这种做法是不安全的! 2.使用委托异...

Qt封装QTcpServer参考资料--QT4中构建多线程的服务器

首先说一下对多线程这个名词的理解过程。以前听说过很多次多线程这个词,而且往往与服务器联系起来,因此一直把多线程误解为服务器特有的功能;直到这次课程设计,仔细学习了一下多线程的机制,才知道真正的意思。简单的来说,就是同时有多个线程一起运行,而不同的线程可以执行不同的操作。举个例子,一个图像处理工具,可以用鼠标一边移动图像,一边用快捷键缩放图像,此时,移动图像...

QT多线程中使用QTcpSocket遇到的读写数据问题

多线程中使用QTcpSocket在run()方法中new QTcpSocket;然后监听readyRead()信号connect(m_pTcpSocket,SIGNAL(readyRead()),this,SLOT(sloat_RecvData())); 问题是当需要给服务器发送一段命令时(使用m_pTcpSocket->write(byteArra...

pthread实现多线程查询(转)

导读:大多数网站的性能瓶颈不在PHP服务器上,因为它可以简单地通过横向增加服务器或CPU核数来轻松应对(对于各种云主机,增加VPS或CPU核数就更方便了,直接以备份镜像增加VPS,连操作系统、环境都不用安装配置),而是在于MySQL数据库。如果用 NoSQL 数据库,也许需要十次查询,才能处理完同样地业务逻辑。此时PHP多线程的作用非常明显,它可以同时执行...