java并发

  并发的本质是通过多线程提高cpu的使用效率。实现可响应的用户界面也是并发的一大亮点。并发技术,功能强大而又复杂难懂,充满魅力,是初级程序员的必修课。

 

  java语言基本的线程机制

 

  定义任务:

  1.实现runnable接口,编写run方法,以实现了该接口的实例作为构造器参数。

  2.实现callable接口,实现call方法。

  

  启动线程

  1.对于第1种任务定义方法,

  a.可以用实现了该接口的实例为构造器参数,构造一个thread实例,然后调用thread.start,从而启动线程。

  b.使用Executors新建一个线程池,线程池分为cachedthreadpool,singlethreadpool和fixthreadpool等,然后调用executorService.execute(实现了runnable接口的实例),从而启动线程,executorservice.shutdown()非常必要,否则线程退出后,jvm不会退出,仍有激活的线程存在。

  2.对于第2种任务定义方法,新建线程池,然后threadpool.submit(实现了callable接口的实例),从而启动线程。submit方法,返回了future实例,通过该实例调用get方法,可以获取call方法的返回值。future.isdone方法判断是否完成,

若不判断,直接get,则该方法一直阻塞至任务完成。

 

  休眠

  TimeUnit.SECOND.sleep();休眠不释放锁,不占用cpu.

 

  优先级

  Thread.currentThread.setPriority();设置优先级,不通平台对优先级的处理不通,最好用max,normal和min

 

  后台进程

  thread.setDaemon(true),非后台进程全部退出时,后台进程也会被杀死。

 

  加入一个线程

  thread.join(),当thread退出或者thread被中断后,当前线程才继续进行

 

  异常处理

  线程抛出异常会直接传播到控制台,可以setuncaughtExceptionhandler来处理异常

 

  处理共享资源

  

  synchronized 或者lock.lock() lock.unlock的方式 lock方式支持公平锁,每次选择等待时间最久的进入临界区。Lock lock=new ReentrantLock(true);

  

  volatitle修饰的成员变量,会直接从内存读取,但是不能保证复杂计算的原子性

 

  atomiclong atomicdouble  atomicrefence 提供了原子性操作

 

  threadlocal在每个线程中都会有一个独立副本

 

  终结任务

  

  线程状态:新建、就绪、阻塞、死亡

  

  进入阻塞的途径:1.wait  2.sleep 3.等待I/O 4在对象上调用同步方法

  

  可中断的阻塞包括sleep和wait,等待I/O的阻塞可以通过关闭底层资源来实现.在对象上调用不通方法,可以用 lock.lockInterruptibly()来支持阻塞。

  

  判断中断 Thread.isInterrputed(),常用例子

while(!Thread.isInterrupted()){
    //todo
}

  

  线程池调用shutdownnow相当于对池中线程调用interrupt(),future的cancel也可以中断

 

  线程之间的协作

  

  wait()  noitfy() notifyall()  wait可以指定线程挂起的时间。三种方法都必须在获得对象锁的情况下调用。wait释放锁。

 

  使用lock的加锁时,协作方法为:Condition condition=lock.newCondition(); condition.await();condition.signal()和signalall()

 

  arrayblockqueue和linkedblockqueue同一个时间只允许一个线程存取。队列为空时,阻塞当前线程。

   

  死锁

  

  构成死锁的四个条件1.构成互斥(线程中使用了不可以共享的资源)2.持有一个资源等待另外一个资源 3.不可以强化资源 4.循环等待

 

  同步构件

 

  countdownlatch :新建时countdownlatch,指定一个size,直到调用了size个countdownlatch的coundown,所有的countdownlatch的await调用都会阻塞该线程。

  

  cyclicbarrier:新建new CyclicBarrier(size,new Runnable),规则与countdownlatch类似,区别是await了size次之后,触发runnable实例的run方法。

 

  delayqueue,可以持有实现了delayed接口的实例引用,delayed接口继承了 comparable接口,所以要实现getDelay()和compateTo()两个方法,只有getDelay返回值小于等于零时,才能从delayqueue中取出。

同时,可取元素的排序使用了compare方法的返回结果。

  

  priorityblockingqueue 支持排序和阻塞,排序根据compare方法,队列为空时,取元素会阻塞当前线程

 

  sheduledExecutorService可以定时启动线程,也可以周期性地启动线程。周期性启动线程时,如果周期时间耗尽后,前一个线程还没有结束,那么将不会启动下一个线程,只到上一个线程结束。

  

  Semaphore: Semaphore semaphore=new Semaphore(size); semaphore.acquire(),semaphore.release()。acquire的次数减去release的次数小于等于size,否则acquire会阻塞当前线程。

 

  Exchanger<T t>:顾名思义,从来在线程间交换T实例。

  

  性能调忧

  

  lcok相比synchronized更加高效,但代码可读性差。

  

  性能:concurrentCollection>copyonwriteCollection>sychronized

 

  免锁容器:copyOnWriteArrayList和copyOnWriteArraySet,concurrentHashMap,concurrentLinkedQueue等,修改时是对副本修改,修改是同步控制的,读取可以同时进行。修改完成后,与原数据进行替换,从而对读取者可见。

  本质是减小加锁的粒度,从而介绍阻塞,提高效率。

 

  乐观加锁:

  原子类,AtomicInteger提供了原子性操作,decrementAndGet。也可以使用客观加锁,compareAndSet(),会将旧值和新值一起提交给该方法,如果提交的旧值与atomic的值不一致,那么该操作会失败。失败后如何操作,要由程序员自己决定。

 

  ReentrantReadAndWritelock=new ReentrantAndWriteLock(); 加锁后,可以多线程读,但如果有写操作,则其他线程不能读也不能写。

 

  

  

  

 

 

 

  

 

  

 

  

 

  

      

  

 

  

转载于:https://www.cnblogs.com/swaggyC/p/6121172.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值