【多线程研究专题一】【Condition使用实例】Conditon与Lock的关系

xiaoxiao2021-02-28  102

以前学习太肤浅了,每次遇到这一话题就卡壳。因此,下定决心深入研究多线程领域,死扣细节。 摘要: Condition和Lock是一对组合,相当于Synchronize和Object.wait()/Object.notify()的关系。 Lock的方法是帮助线程获取锁,Condition的方法是帮助线程释放锁。 参考API Doc: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html condition.await使用说明,可参考Lock.bewCondition()的方法说明:     /**      * Returns a new {@link Condition} instance that is bound to this      * {@code Lock} instance.      *      * <p> Before waiting on the condition the lock must be held by the      * current thread.      *A call to {@link Condition#await()}will atomically release the lock      * before waiting and re-acquire the lock before the wait returns.      *      * <p><b> Implementation Considerations </b>      *      * <p> The exact operation of the {@link Condition} instance depends on      * the {@code Lock} implementation and must be documented by that      * implementation.      *      * @return A new {@link Condition} instance for this {@code Lock} instance      * @throws UnsupportedOperationException if this {@code Lock}      *         implementation does not support conditions      */     ConditionnewCondition(); 再啰嗦下:Condition是从Lock的方法newCondition()获取的,要求lock后,再执行condition的方法,不然会报错。 原理:就像wait() notify()那样,condition.await()和condition.singal()两个方法,最后一步是释放锁,所以对应地要求,在之前,该方法获取了锁。 ===============错误Demo演示================== Condition可封装在一个Helper操作类,把wait之后的操作写到一个函数。如下: package basic; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class FutureTaskWithConditionAndTimerTest {     static Callable<String> callable = new AsyncCallable();     static Lock lock = new ReentrantLock();     static Condition condition = lock.newCondition();     public static void main(String[] args) throws InterruptedException, ExecutionException {         FutureTask<String> task = new FutureTask<String>(callable);         ExecutorService exe = Executors.newCachedThreadPool();         exe.submit(task);         System.out.println("Future Task is Already submited!");         System.out.println("waiting future task feedback...");         //另一个线程等待。Timer自带一个线程。         Timer timer = new Timer();         timer.schedule(new TimerTask() {             @Override             public void run() {                 System.out.println("Time up. notify the other thread by condition.signal!");                 condition.signal();             }         }, 3000);         String result = task.get();         System.out.printf("Async result is :%s",result);     }     public static class AsyncCallable implements Callable{         @Override         public String call() throws Exception {             //Thread.sleep(3000);             //与Thread写法对比:由sleep阻塞改为等待wait             condition.await();             String result = "Test Call Feedback";             return result;         }     } } 错误如下: Exception in thread "main" java.util.concurrent.ExecutionException : java.lang.IllegalMonitorStateException       at java.util.concurrent.FutureTask.report(Unknown Source)       at java.util.concurrent.FutureTask.get(Unknown Source)       at basic.FutureTaskWithConditionAndTimerTest.main( FutureTaskWithConditionAndTimerTest.java:41 ) Caused by: java.lang.IllegalMonitorStateException       at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)       at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)       at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(Unknown Source)       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)       at basic.FutureTaskWithConditionAndTimerTest$AsyncCallable.call( FutureTaskWithConditionAndTimerTest.java:53 )       at basic.FutureTaskWithConditionAndTimerTest$AsyncCallable.call( FutureTaskWithConditionAndTimerTest.java:1 )       at java.util.concurrent.FutureTask.run(Unknown Source)       at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)       at java.util.concurrent.FutureTask.run(Unknown Source)       at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)       at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)       at java.lang.Thread.run(Unknown Source) Time up. notify the other thread by condition.signal! Exception in thread "Timer-0" java.lang.IllegalMonitorStateException       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(Unknown Source)       at basic.FutureTaskWithConditionAndTimerTest$1.run( FutureTaskWithConditionAndTimerTest.java:36 )       at java.util.TimerThread.mainLoop(Unknown Source)       at java.util.TimerThread.run(Unknown Source) Java.lang.IllegalMonitorStateException   违法的监控状态异常。当某个线程试图等待一个自己并不拥有的对象(O)的监控器或者通知其他线程等待该对象(O)的监控器时,抛出该异常。 http://blog.csdn.net/intlgj/article/details/6245226 原因是:condition方法的调用之前要加lock。不然该线程还没获取到锁。所以在释放锁的时候,Monitor为空 注意:这里要用可重入锁,不然会出现嵌套锁死现象。例如把两个condition方法都用synchronize声明,则callAction的那个方法,因为一直wait(),没有执行完毕,所以一直持有锁,另一个方法,changeStatus()就无法获得锁,一直阻塞。 可参考: http://luan.iteye.com/blog/1849712 正确代码如下: package basic; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionLockTest {        public static void main(String[] args ) {                           final ConditionHelper helper = new ConditionHelper();                                       Thread thread = new Thread( new Runnable() {                                       @Override                    public void run() {                                                   try {                                helper .callAction();                         } catch (InterruptedException e ) {                                // TODO Auto-generated catch block                                e .printStackTrace();                         }                   }             });              thread .start();                          Timer timer = new Timer();              timer .schedule( new TimerTask() {                                       @Override                    public void run() {                          try {                                helper .changeStatus();                         } catch (InterruptedException e ) {                                // TODO Auto-generated catch block                                e .printStackTrace();                         }                   }             }, 3000);                    }               public static class ConditionHelper{                          Lock lock = new ReentrantLock();             Condition condition = lock .newCondition();              boolean waiteStatus = true ;                           public void callAction() throws InterruptedException{                    lock .lockInterruptibly();                                       try {                         System. out .println( "going to wait" );                          while ( waiteStatus ) {                                       try {                                      condition .await();                               } catch (InterruptedException e ) {                                      // TODO Auto-generated catch block                                      e .printStackTrace();                               }                         }                                                  System. out .println( "End!" );                          waiteStatus = true ;                   } finally {                          lock .unlock();                   }             }                           public void changeStatus() throws InterruptedException{                    lock .lockInterruptibly();                    try {                          waiteStatus = false ;                          condition .signal();                   } finally {                          lock .unlock();                   }             }                    } } 运行结果: going to wait End!
转载请注明原文地址: https://www.6miu.com/read-79784.html

最新回复(0)