JAVA多线程-Lock的使用(一)-ReentrantLock与Condition

JAVA多线程-Lock的使用

      本节主要介绍使用Java5中的Lock对象也能实现同步的效果,而且在使用上更加方便。

一、使用ReentrantLock类

     在java多线程中,可以使用synchronized关键字来实现线程之间同步互斥,但在JDK1.5中新增加了ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定多路分支通知等功能,并且在使用上也比synchronized更加的灵活。

     1.1 使用ReentrantLock实现同步:测试

package org.jksoft.thread.reentrantLock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 测试一:使用ReentrantLock去实习线程间的同步
 * @author mcl
 *
 * 2016-2-21-上午11:11:46
 */
public class Test1 {
	public static void main(String[] args) {
		MyService service = new MyService();
		for(int i =0;i<10;i++){
			new ThreadA(service).start();
		}
	}
}
class ThreadA extends Thread{
	private MyService service;
	public ThreadA(MyService service){
		this.service = service;
	}
	public void run(){
		service.print();
	}
}
class MyService{
	private Lock lock = new ReentrantLock();
	public void print(){
		//获取锁
		lock.lock();
		for(int i=0;i<5;i++){
			System.out.println(Thread.currentThread().getName()+" : "+(i+1));
		}
		//释放锁
		lock.unlock();
	}
}
    结果: 

   

  分析: 我们可以看到,每个线程都是等待上一个线程打印完毕之后,才继续打印,因为当前线程已经持有锁,但线程之间打印的顺序是随机的。

  1.2 使用condition去实现等待/通知

package org.jksoft.thread.reentrantLock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 测试二:使用condition实现等待/通知 注意:wait与notify都是需要在同步代码块中调用,也就是必须持有当前锁
 * 所以condition中的await()与signal()也同样必须持有当前锁
 * 
 * @author mcl
 * 
 *         2016-2-21-上午11:11:46
 */
public class Test2 {
	public static void main(String[] args) {
		MyService2 service = new MyService2();
		ThreadB thread = new ThreadB(service );
		thread.start();
		try {
			Thread.sleep(3000);
			service.signal();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class ThreadB extends Thread{
	private MyService2 service;
	public ThreadB(MyService2 service){
		this.service = service;
	}
	public void run(){
		service.await();
	}
}
class MyService2 {
	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	public void await() {
		try {
			lock.lock();
			System.out.println("A");
			condition.await();
			System.out.println("B");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("锁被释放了");
		}
	}
	public void signal(){
		try {
			lock.lock();
			condition.signal();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}
    结果: 线程B先执行await()等待通知,主线程睡3s后,调用service的signal()方法,唤醒处于waiting状态的线程B。

1.3 使用多个condition实现通知部分线程:

package org.jksoft.thread.reentrantLock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 测试三:使用多个condition实现线程部分通知
 * 
 * @author mcl
 * 
 *         2016-2-21-上午11:11:46
 */
public class Test3 {
	public static void main(String[] args) {
		MyService3 service = new MyService3();
		ThreadC thread = new ThreadC(service );
		thread.start();
		ThreadD thread2 = new ThreadD(service );
		thread2.start();
		try {
			Thread.sleep(3000);
			service.Asignal();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class ThreadC extends Thread{
	private MyService3 service;
	public ThreadC(MyService3 service){
		this.service = service;
	}
	public void run(){
		service.Aawait();
	}
}
class ThreadD extends Thread{
	private MyService3 service;
	public ThreadD(MyService3 service){
		this.service = service;
	}
	public void run(){
		service.Bawait();
	}
}
class MyService3 {
	private Lock lock = new ReentrantLock();
	private Condition conditionA = lock.newCondition();
	private Condition conditionB = lock.newCondition();
	public void Aawait() {
		try {
			lock.lock();
			System.out.println("C...等待");
			conditionA.await();
			System.out.println("C...被唤醒");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	public void Bawait() {
		try {
			lock.lock();
			System.out.println("D...等待");
			conditionA.await();
			System.out.println("D...被唤醒");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("锁被释放了");
		}
	}
	public void Asignal(){
		try {
			lock.lock();
			conditionA.signal();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	public void Bsignal(){
		try {
			lock.lock();
			conditionB.signal();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}
     运行结果:  线程C(基于conditionA)和线程D(基于conditionB)都存于等待状态,主线程在3s后,利用conditionA唤醒了线程C,而线程D依旧处于等待状态,这也就达到了我们利用多个condition去部分通知等待线程。

 

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值