Java多线程(4)——多线程JDK5.0升级版(传智播客毕老师视频讲解)

来源:互联网 发布:芝加哥艺术学院 知乎 编辑:程序博客网 时间:2024/05/18 00:18

在Java的JDK1.5版本(即5.0版本)以后,api在java,util.concurrent.locks包中提供了Lock接口与Condition接口。




例子

拿上一篇生产者消费者的例子来说:

构建生产者—消费者

1.1、synchronized变为了ReentrantLock对象的lock()方法;

1.2、wait()、notify()、notifyAll()变为了Condition对象的await()、signal()、signalAll();

代码如下:

import java.util.concurrent.locks.*;public class Jdk5Test {private int num;private int value;private boolean flag=true;private ReentrantLock lock=new ReentrantLock();private Condition pro=lock.newCondition();private Condition con=lock.newCondition();public  void setMessage(int num,int value){lock.lock();                //上锁try{Thread.sleep(100);}catch(Exception e){}while(!flag)                //如过flag为假,表示当前已生产,则生产线程await()try{pro.await();}catch(Exception e){}   //由于await()有异常声明,所以应catch或者throwsthis.num=num;               //生产this.value=value;System.out.println(Thread.currentThread().getName()+"......."+"生产"+".."+this.num);flag=false;                 //生产完毕后,将flag置为假con.signal();               //唤醒消费线程lock.unlock();              //解锁}public  void getMessage(){lock.lock();                //上锁try{Thread.sleep(100);}catch(Exception e){}while(flag)                 //如过flag为真,表示当前已消费,则消费线程await()try{con.await();}catch(Exception e){}System.out.println(Thread.currentThread().getName()+"......."+"消费"+"......."+this.num);flag=true;                  //消费完毕后,将flag置为真pro.signal();               //唤醒生产线程lock.unlock();              //解锁}}public class Producer implements Runnable{private Jdk5Test r;int num=0;int value=5;public  Producer(Jdk5Test r){this.r=r;}public void run(){while(true){r.setMessage(num++,value);}}}public class Consumer implements Runnable{private Jdk5Test r;public Consumer(Jdk5Test r){this.r=r;}public void run(){while(true){r.getMessage();}}}public class Wakeup {public static void main(String arg[]){Jdk5Test r=new Jdk5Test();Producer r1=new Producer(r);//线程1Producer r2=new Producer(r);Consumer r3=new Consumer(r);//线程2Consumer r4=new Consumer(r);Thread t1=new Thread(r1);Thread t2=new Thread(r2);Thread t3=new Thread(r3);Thread t4=new Thread(r4);t1.start();t2.start();t3.start();t4.start();}}
运行结果如下:


可见,与之前的synchronized、wait、notify没多大区别,但是lock()与unlock()方法使上锁与解锁明朗化,能很容易理解,同时可以声明两个condition类对象,使得在不用全部唤醒而只需唤醒对方即可,效率提高!

但是其本质与synchronized等方法没什么不同;

值得注意的是:

await()方法在调用后没有解锁的功能,因此如果awati()真的报出异常,则程序会执行异常处理,而由于其没有释放掉锁,因此别的线程进不来,导致程序出现死锁的可能;而释放锁相当于释放资源,其为异常发生后必须执行的动作,因此用finally中写如unlock方法;修改代码如下:

import java.util.concurrent.locks.*;public class Jdk5Test {private int num=0;private int value;private boolean flag=true;private ReentrantLock lock=new ReentrantLock();private Condition pro=lock.newCondition();private Condition con=lock.newCondition();public  void setMessage() throws InterruptedException{lock.lock();                     //上锁try{Thread.sleep(100);}catch(Exception e){}try{while(!flag)                //如过flag为假,表示当前已生产,则生产线程await()pro.await();            //由于await()有异常声明,所以应catch或者throwsnum++;                      //生产System.out.println(Thread.currentThread().getName()+"......."+"生产"+".."+this.num);flag=false;                 //生产完毕后,将flag置为假con.signal();               //唤醒消费线程}finally{lock.unlock();              //解锁(必须执行的动作)}}public  void getMessage() throws InterruptedException{lock.lock();                    //上锁try{Thread.sleep(100);}catch(Exception e){}try{while(flag)                 //如过flag为真,表示当前已消费,则消费线程await()con.await();System.out.println(Thread.currentThread().getName()+"......."+"消费"+"......."+this.num);flag=true;                  //消费完毕后,将flag置为真pro.signal();               //唤醒生产线程}finally{lock.unlock();              //解锁(必须执行的动作)}}}
此异常抛出后,调用其方法的函数内应进行处理,即捕获或者继续抛出,但由于调用其方法的函数为run方法,而run方法其是实现接口Runnable的,在Runnable中没有对run方法进行异常声明,所以其实现子类不允许再往外抛出异常,即应进行内部处理,所以生产线程和消费线程代码修改如下:

public class Producer implements Runnable{private Jdk5Test r;public  Producer(Jdk5Test r){this.r=r;}public void run(){while(true){try{r.setMessage();}catch(InterruptedException e){}}}}public class Consumer implements Runnable{private Jdk5Test r;public Consumer(Jdk5Test r){this.r=r;}public void run(){while(true){try{r.getMessage();}catch(InterruptedException e){}}}}

















0 0
原创粉丝点击