在jdk1.5并发包中引入的Lock,其主要实现重入锁,和读写锁,并且相对于synchronized原生的将锁的获取和释放显示化,并且可以提供了非阻塞的获取锁,并结合condition实现多路分之,将条件更加细化,并且比synchronized效率更高,但是在jdk1.6,对synchronized做出了很多优化,所以性能不一定比lock差,下面给出使用lock来实现等待/唤醒和之前的生产者消费者同步问题的代码:
package com.zcj.thread03;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void waitTest(){
lock.lock();
try{
System.out.println("我开始等待,等待被唤醒!");
condition.await();
System.out.println("我已经被唤醒!");
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void signalTest(){
lock.lock();
System.out.println("我唤醒等待线程");
condition.signal();
lock.unlock();
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
ThreadA threadA = new ThreadA(lockTest);
ThreadB threadB = new ThreadB(lockTest);
threadA.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
threadB.start();
}
}
class ThreadA extends Thread{
private LockTest lockTest;
public ThreadA(LockTest lockTest){
this.lockTest = lockTest;
}
@Override
public void run(){
lockTest.waitTest();
}
}
class ThreadB extends Thread{
private LockTest lockTest;
public ThreadB(LockTest lockTest){
this.lockTest = lockTest;
}
@Override
public void run(){
lockTest.signalTest();
}
}
单个消费者和单个生产者的同步代码如下:
package com.zcj.thread03;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private int count=1;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private Condition condition2 = lock.newCondition();
public void produce(){
lock.lock();
try{
if(count==1){
condition.await();
}
count=1;
System.out.println("生产者生产商品!");
condition2.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void consume(){
lock.lock();
try{
if(count==0){
condition2.await();
}
count=0;
System.out.println("消费者消费商品!");
condition.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
ThreadA threadA = new ThreadA(lockTest);
ThreadB threadB = new ThreadB(lockTest);
threadA.start();
threadB.start();
}
}
class ThreadA extends Thread{
private LockTest lockTest;
public ThreadA(LockTest lockTest){
this.lockTest = lockTest;
}
@Override
public void run(){
while(true){
lockTest.produce();
}
}
}
class ThreadB extends Thread{
private LockTest lockTest;
public ThreadB(LockTest lockTest){
this.lockTest = lockTest;
}
@Override
public void run(){
while(true){
lockTest.consume();
}
}
}
从代码中可以看出使用lock我们可以指定唤醒什么条件下的线程
接下来编写多个消费者和多个生产者,只需要把if改为while和signal改为signalAll即可,代码如下:
package com.zcj.thread03;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private int count=1;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private Condition condition2 = lock.newCondition();
public void produce(){
lock.lock();
try{
while(count==1){
condition.await();
}
count=1;
System.out.println(Thread.currentThread().getName()+"生产者生产商品!");
condition2.signalAll();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void consume(){
lock.lock();
try{
while(count==0){
condition2.await();
}
count=0;
System.out.println(Thread.currentThread().getName()+"消费者消费商品!");
condition.signalAll();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
ThreadA threadA = new ThreadA(lockTest);
ThreadA threadA1 = new ThreadA(lockTest);
ThreadB threadB = new ThreadB(lockTest);
ThreadB threadB1 = new ThreadB(lockTest);
threadA.start();
threadA1.start();
threadB.start();
threadB1.start();
}
}
class ThreadA extends Thread{
private LockTest lockTest;
public ThreadA(LockTest lockTest){
this.lockTest = lockTest;
}
@Override
public void run(){
while(true){
lockTest.produce();
}
}
}
class ThreadB extends Thread{
private LockTest lockTest;
public ThreadB(LockTest lockTest){
this.lockTest = lockTest;
}
@Override
public void run(){
while(true){
lockTest.consume();
}
}
}