java5之后引入了java.util.concurrent包,专门用于解决java多线程问题。
 
AtomicInteger用于解决原子性操作(i++,i--的问题):
AtomicInteger age=100;//必须定义在类的成员变量中,这样多个线程才能共同操作。如果定义在类的方法中作为局部变量,那么将存在于java虚拟机栈中,各个线程操作的是不同的变量,就不存在同步的问题。
 
Executors是并发编程库中的工具类,用于创建线程池:
ExecutorService threadPool=Executors.newFixedThreadPool(3);创建一个固定大小为3的线程池
Executors.newCachedThreadPool();创建一个缓存线程池,有多少任务就创建多少个线程
Executors.newSingleThreadExecutor();创建一个唯一的单线程
 
ExecutorService继承自Executor接口,所以具有execute(Runnable command)方法
threadPool.execute(new Runnable(){
     public void run(){
        //执行任务的代码
}
});
-------------------------------------------------------------------------------
//提交的是一个任务(Callable:可调用的任务),可以得到返回的结果
Future<T> future=threadPool.submit(new Callable<T>(){
      pulbic <T> call()throws Exception{
                //执行任务的代码
}
});
future.get()得到线程执行完后的结果
-------------------------------------------------------------------------------
java5之后,不再使用synchronized关键字,而是使用锁对象对代码进行加锁。
Lock lock=new ReentrantLock();
(ReentrantLock顾名思义就是锁可以重入,一个线程持有锁,state=1,如果它再次调用lock方法,那么他将继续拥有这把锁,state=2.当前可重入锁要完全释放,调用了多少次lock方法,还得调用等量的unlock方法来完全释放锁)
lock.lock();对代码块加锁
try{
       ....//执行相关代码
}finally{
    lock.unlock();释放锁
}
为什么要使用try...finally...语句呢?如果代码块抛出异常,那么程序将直接跳出并返回到被调用的上一级模块,而锁却一直没有被释放。
---------------------------------------------------------------------------------
读写锁:分为读锁和写锁。读锁与读锁不互斥(同个线程可以同时读一个数据),读锁与写锁互斥,写锁与写锁互斥(在读的时候不能写,在写的时候也不能写)
ReadWriteLock lock=new ReentrantReadWriteLock();//可重入的读写锁
lock.readLock().lock();//lock对象首先获得读锁,然后对代码进行加锁
lock.readLock().unlock();释放读锁
lock.writeLock().lock();//lock对象首先获得写锁,然后对代码进行加锁
lock.writeLock().unlock();释放写锁
 
缓存:
CachedData缓存数据:
多个线程可以同时访问缓存中的数据,并加上读锁,当某个线程发现里面没有数据的时候,需要往里面写数据,这时就需要挂上写锁,通知其他线程,此时不能进来读数据。以下代码为缓存的伪代码实现(只要能够写出伪代码,就能够写出程序了):
Map<String,Object> cachedData=new HashMap<String,Object>();
ReadWriteLock lock=new ReentrantReadWriteLock();
public Object getData(String key){
lock.readLock().lock();
Object value=cachedData.get(key);
if(value==null){
    lock.readLock().unlock();
    lock.writeLock().lock();
    value="aaa";//实际代码为:从数据库中查找
    lock.writeLock().unlock();
    lock.ReadLock().lock();
}
lock.readLock().unlock();
return value;
}
----------------------------------------------------------------------------------------------------------------
java5的Lock用于解决线程互斥的问题,线程同步的问题则用Condition来解决,其作用类似于传统的wait()和notify()方法。
线程要同步(我做完了某件事之后再通知你做),必须要先互斥才行,所以首先得获取锁对象并上锁:
Lock lock=new ReentrantLock();
Condition condition=lock.newConditon();
boolean flag=true;
if(!flag){   //此处最好使用while,防止虚假唤醒
   //只有当flag为true时才执行相关操作,否则需要等待
    condition.await();
}
......//执行代码
condition.signal();//唤醒其他线程
lock.unlock();//并且释放锁
------------------------------------------------------------------------------------------------------------------
Condition较wait()、notify()的优势在于:一个锁内部可以有多个Condition对象,能够实现多路等待和通知。
阻塞队列的实现:
Lock lock=new ReentrantLock();
Condition notFull=lock.newConditon();
Condition notEmpty=lock.newCondition();
Object[] items=new Object[100];//阻塞队列的容量为100
int count=0;//记录当前阻塞队列中对象的个数
int putptr=0;//记录放数组的指针
int takeptr=0;//记录取数组的指针
public void put(Object x){
    lock.lock();//首先就要加一个锁,我在放对象的时候,其他线程不能放
    while(count==items.length){
            notFull.await();
}
items[putptr]=x;
if(++putptr==items.length){
    putptr=0;//如果指针达到数组末尾,则需要重新回到0的位置
}
++count;
notEmpty.signal();//唤醒另外一把取锁
lock.unlock();
}
 
public Object take(){
    lock.lock();//当我在取对象的时候,其他线程是不能够取的
    while(count==0){
        notEmpt.await();
}
Object x=items[takeptr];
if(++takeptr==items.length){
    takeptr=0;
}
count--;
notFull.signal();//唤醒另外一把放锁
}
--------------------------------------------------------------------------------------------------------
Semaphore信号灯(线程同步的工具类):必须获得某段代码的信号灯,线程才能够执行该段代码,执行完之后需要释放信号灯,供其他线程竞争。如果只有一盏信号灯,可以实现互斥锁的功能(即厕所只有一个坑),如果有3盏信号灯,即代表有3个厕所坑,4个线程来访问的话,只能同时进入3个,还有一个需要在外面等待。
Semaphore sp=new Semaphore(3);
for(int i=0;i<4;i++){//有四个线程,但是每个对象执行前都必须要获得信号灯
    new Thread(new Runnable(){
        void run(){
            sp.acquire();//线程首先需要获得信号灯,如果没有获得到,则挂起,暂时不往下执行
            .....//执行相关代码
            sp.release();//执行完之后,线程需要释放信号灯
        }
    }).start();
}
---------------------------------------------------------------------------------------------------------------
ArrayBlockingQueue 阻塞队列(以数组方式实现),实现了BlockingQueue接口:put() 和take()方法具有阻塞功能
LinkedBlockingQueue阻塞队列,以链表方式实现,大小不固定
 
同步集合:
如果HashMap被多个线程同时访问,则会导致线程不安全,这时就需要使用ConcurrentHashMap
ArrayList也是线程不安全的,但使用Iterator迭代的时候不能修改容器中的元素,这时需要用到CopyOnWriteArrayList
 

java5引入的并发编程库的更多相关文章

  1. C++11 并发编程库

    C++11 并发编程 C++11 新标准中引入了几个头文件来支持多线程编程,他们分别是: <atomic>:该头文主要声明了两个类, std::atomic 和 std::atomic_f ...

  2. 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

      Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...

  3. 【Java并发编程】:并发新特性—Executor框架与线程池

    Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...

  4. Google Java编程库Guava介绍

    本系列想介绍下Java下开源的优秀编程库--Guava[ˈgwɑːvə].它包含了Google在Java项目中使用一些核心库,包含集合(Collections),缓存(Caching),并发编程库(C ...

  5. c++ 11开始语言本身和标准库支持并发编程

    c++ 11开始语言本身和标准库支持并发编程,意味着真正要到编译器从语言和标准库层面开始稳定,估计得到17标准出来.14稳定之后的事情了,根据历史经验,新特性的引入到稳定被广泛采用至少要一个大版本的跨 ...

  6. Java并发编程面试题 Top 50 整理版

    本文在 Java线程面试题 Top 50的基础上,对部分答案进行进行了整理和补充,问题答案主要来自<Java编程思想(第四版)>,<Java并发编程实战>和一些优秀的博客,当然 ...

  7. Java并发编程75道面试题及答案

    1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...

  8. Java并发编程75个问答

    1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...

  9. Java并发编程73道面试题及答案

    原文出处:https://blog.csdn.net/qq_34039315/article/details/7854931 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线 ...

随机推荐

  1. phpstrom如何定义文件打开的方式

    今天想vue结合PHP来小写一段代码,但是发现自己把vue的文件放进去,会显示text文本,在刚开始的时候,编辑器会提示我们以什么格式打开,我没在意的选择了text,结果悲催了,那么在设置里面的哪个选 ...

  2. 在scrollview中双击定点放大的代码

    双击放大是 iPhone 的一个基本操作,第三方程序里引入这一功能的话,主要是在 scrollview 呈现一张图片或者 PDF 页面时,双击可以放大,主要代码如下 - (void)scrollVie ...

  3. sql 提升查询效率 group by option hash group

    问题: 一个程序查询经常超过20siis限制时间,排查问题后发现其中的一个存储过程时间会在15s左右 解决思路: 1:确认问题点 通过输出时间的方式查看存储过程中每个部分的执行时间,找到最耗时的三个过 ...

  4. 【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树

    [BZOJ3626][LNOI2014]LCA Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度 ...

  5. unicode转换中文

    <!doctype html><html lang="en"> <head>  <meta http-equiv="Refres ...

  6. 170425、centos安装mysql5.6数据库

    # rpm -qa | grep mysql ## 查看该操作系统上是否已经安装了 mysql 数据库, 有的话,可以通过 rpm -e 命令 或者 rpm -e --nodeps 命令来卸载掉 # ...

  7. 160513、nginx+tomcat集群+session共享(linux)

    第一步:linux中多个tomcat安装和jdk安装(略) 第二步:nginx安装,linux中安装nginx和windows上有点不同也容易出错,需要编译,这里做介绍 一.安装依赖 gcc open ...

  8. 修改mysql root的秘密

    修改mysql root的秘密 ');

  9. hdu2094—看似拓扑实际上是一道思维题

    HDU2094  产生冠军 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2094 题意:中文题,就不解释了.题意已经非常清楚了. 这道题的看起来像是一 ...

  10. 【Django错误】OSError: raw write() returned invalid length 14 (should have been between 0 and 7)

    错误环境 使用Django框架创建完models类的之后,用python manage.py migrate命令来生成数据库表的时候出错 错误代码 Operations to perform: App ...