Java5 并发库_java5引入的并发编程库

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 future=threadPool.submit(new Callable(){

pulbic 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 cachedData=new HashMap();

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值