Java5.0多线程编程

[size=large]
Lock接口

ReentrantLock是Lock的具体类,Lock提供了以下一些方法:

lock(): 请求锁定,如果锁已被别的线程锁定,调用此方法的线程被阻断进入等待状态。
tryLock():如果锁没被别的线程锁定,进入锁定状态,并返回true。若锁已被锁定,返回false,不进入等待状态。此方法还可带时间参数,如果锁在方法执行时已被锁定,线程将继续等待规定的时间,若还不行才返回false。
unlock():取消锁定,需要注意的是Lock不会自动取消,编程时必须手动解锁。 来源:www.examda.com
代码:

//生成一个锁

Lock lock = new ReentrantLock();

public void accessProtectedResource() {

lock.lock(); //取得锁定

try {

//对共享资源进行操作

} finally {

//一定记着把锁取消掉,锁本身是不会自动解锁的

lock.unlock();

}

}


ReadWriteLock接口

为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。ReadWriteLock可满足这种需要。ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock,而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有:

readLock(): 返回一个读的lock 来源:www.examda.com
writeLock(): 返回一个写的lock, 此lock是排他的。
ReadWriteLock的例子:

public class FileOperator{

//初始化一个ReadWriteLock

ReadWriteLock lock = new ReentrantReadWriteLock();

public String read() {

//得到readLock并锁定

Lock readLock = lock.readLock();

readLock.lock();

try {

//做读的工作

return "Read something";

} finally {

readLock.unlock();

}

}



public void write(String content) {

//得到writeLock并锁定

Lock writeLock = lock.writeLock();

writeLock.lock();

try {

//做读的工作

} finally {

writeLock.unlock();

}

}

}

需要注意的是ReadWriteLock提供了一个高效的锁定机理,但最终程序的运行效率是和程序的设计息息相关的,比如说如果读的线程和写的线程同时在等待,要考虑是先发放读的lock还是先发放写的lock。如果写发生的频率不高,而且快,可以考虑先给写的lock。还要考虑的问题是如果一个写正在等待读完成,此时一个新的读进来,是否要给这个新的读发锁,如果发了,可能导致写的线程等很久。等等此类问题在编程时都要给予充分的考虑。

Condition接口:

有时候线程取得lock后需要在一定条件下才能做某些工作,比如说经典的Producer和Consumer问题,Consumer必须在篮子里有苹果的时候才能吃苹果,否则它必须暂时放弃对篮子的锁定,等到Producer往篮子里放了苹果后再去拿来吃。而Producer必须等到篮子空了才能往里放苹果,否则它也需要暂时解锁等Consumer把苹果吃了才能往篮子里放苹果。在Java 5.0以前,这种功能是由来Object类的wait(), notify()和notifyAll()等方法实现的,在5.0里面,这些功能集中到了Condition这个接口来实现,Condition提供以下方法:
await():使调用此方法的线程放弃锁定,进入睡眠直到被打断或被唤醒。
signal(): 唤醒一个等待的线程
signalAll():唤醒所有等待的线程
Condition的例子:

public class Basket {

Lock lock = new ReentrantLock();

//产生Condition对象

Condition produced = lock.newCondition();

Condition consumed = lock.newCondition();

boolean available = false;



public void produce() throws InterruptedException {

lock.lock();

try {

if(available){

consumed.await(); //放弃lock进入睡眠

}

/*生产苹果*/

System.out.println("Apple produced.");

available = true;

produced.signal(); //发信号唤醒等待这个Condition的线程

} finally {

lock.unlock();

}

}



public void consume() throws InterruptedException {

lock.lock();

try {

if(!available){

produced.await();//放弃lock进入睡眠

}

/*吃苹果*/

System.out.println("Apple consumed.");

available = false;

consumed.signal();//发信号唤醒等待这个Condition的线程

} finally {

lock.unlock();

}

}

}

ConditionTester:

public class ConditionTester {



public static void main(String[] args) throws InterruptedException{

final Basket basket = new Basket();

//定义一个producer

Runnable producer = new Runnable() {

public void run() {

try {

basket.produce();

} catch (InterruptedException ex) {

ex.printStackTrace();

}

}

};

//定义一个consumer

Runnable consumer = new Runnable() {

public void run() {

try {

basket.consume();

} catch (InterruptedException ex) {

ex.printStackTrace();

}

}

};

//各产生10个consumer和producer

ExecutorService service = Executors.newCachedThreadPool();

for(int i=0; i < 10; i++)

service.submit(consumer);

Thread.sleep(2000);

for(int i=0; i<10; i++)

service.submit(producer);

service.shutdown();

}

}

   Java 5.0里新加了4个协调线程间进程的同步装置,它们分别是Semaphore, CountDownLatch, CyclicBarrier和Exchanger.

Semaphore:

   用来管理一个资源池的工具,Semaphore可以看成是个通行证,线程要想从资源池拿到资源必须先拿到通行证,Semaphore提供的通行证数量和资源池的大小一致。如果线程暂时拿不到通行证,线程就会被阻断进入等待状态。以下是一个例子:

public class Pool {

      ArrayList pool = null;

      Semaphore pass = null;

      public Pool(int size){

            //初始化资源池

            pool = new ArrayList();

            for(int i=0; i

                  pool.add("Resource "+i);

            }

            //Semaphore的大小和资源池的大小一致

            pass = new Semaphore(size);

      }

      public String get() throws InterruptedException{

            //获取通行证,只有得到通行证后才能得到资源

            pass.acquire();

            return getResource();

      }

      public void put(String resource){

            //归还通行证,并归还资源

            pass.release();

            releaseResource(resource);

      }

     private synchronized String getResource() {

            String result = pool.get(0);

            pool.remove(0);

            System.out.println("Give out "+result);

            return result;

      }

      private synchronized void releaseResource(String resource) {

            System.out.println("return "+resource);

            pool.add(resource);

      }

}

SemaphoreTest:

public class SemaphoreTest {

      public static void main(String[] args){

            final Pool aPool = new Pool(2);

            Runnable worker = new Runnable() {

                  public void run() {

                        String resource = null;

                        try {

                              //取得resource

                              resource = aPool.get();

                        } catch (InterruptedException ex) {

                              ex.printStackTrace();

                        }

                        //用resource做工作

                        System.out.println("I worked on "+resource);

                        //归还resource

                        aPool.put(resource);

                  }

            };

            ExecutorService service = Executors.newCachedThreadPool();

            for(int i=0; i<20; i++){

                  service.submit(worker);

            }

            service.shutdown();

      }    

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值