public class MyService { private Lock lock = new ReentrantLock(); public void testMethod() { lock.lock(); //获取锁,线程就持有了“对象监视器” for (int i=0; i<3; i++) { System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i+1))); } lock.unlock(); //释放锁 } }
public class MyThread extends Thread { private MyService myService; public MyThread(MyService myService) { this.myService = myService; } public void run() { myService.testMethod(); } }
public class Run { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThread a1 = new MyThread(service); MyThread a2 = new MyThread(service); a1.start(); a2.start(); } }
ThreadName=Thread-1 1 ThreadName=Thread-1 2 ThreadName=Thread-1 3 ThreadName=Thread-0 1 ThreadName=Thread-0 2 ThreadName=Thread-0 3 |
关键字synchronized与waits和notifyn/notifyAll()方法相结合可以实现等待/通知模式,类ReentrantLock也可以实现同样的功能,但需要借助于Condition对象。Condition类是在JDK5中出现的技术,使用它有更好的灵活性,比如可以实现多路通知功能,也就是在一个Lock对象里面可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。
在使用notify()/notifyAll()方法进行通知时,被通知的线程却是由JVM随机选择的。但使用ReentrantLock结合Condition类是可以实现前面介绍过的“选择性通知”,这个功能是非常重要的,而且在Condition类中是默认提供的。
而synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册在它一个对象的身上。线程开始notifyAll()时,需要通知所有的WAITING线程,没有选择权,会出现相当大的效率问题。
public class MyService { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void await() { try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } }自定义线程
public class MyThread1 extends Thread { private MyService service; public MyThread1(MyService service) { this.service = service; } @Override public void run() { service.await(); } }
public class Run { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThread1 a1 = new MyThread1(service); a1.start(); } }
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:155) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1260) at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1723) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await |
public class MyService { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void await() { try { lock.lock(); System.out.println("await 时间为: " + System.currentTimeMillis()); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signal() { try { lock.lock(); System.out.println("signal 时间为:" + System.currentTimeMillis()); condition.signal(); } finally { lock.unlock(); } } }
public class MyThread1 extends Thread { private MyService service; public MyThread1(MyService service) { this.service = service; } @Override public void run() { service.await(); } }
public class Run { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThread1 a1 = new MyThread1(service); a1.start(); Thread.sleep(1000); service.signal(); } }
await 时间为: 1462595312580 signal 时间为:1462595313580 |
public class MyService { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); //一个公共的 public void awaitA() { try { lock.lock(); System.out.println(" begin awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); condition.await(); System.out.println(" end awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void awaitB() { try { lock.lock(); System.out.println(" begin awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); condition.await(); System.out.println(" end awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signalAll() { try { lock.lock(); System.out.println("signal 时间为:" + System.currentTimeMillis()); condition.signalAll(); } finally { lock.unlock(); } } }
public class MyThread1 extends Thread { private MyService service; public MyThread1(MyService service) { this.service = service; } @Override public void run() { service.awaitA(); } }
public class MyThread2 extends Thread{ private MyService service; public MyThread2(MyService service) { this.service = service; } @Override public void run() { service.awaitB(); } }
public class Run { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThread1 a = new MyThread1(service); a.setName("AA"); a.start(); MyThread2 b = new MyThread2(service); b.setName("BB"); b.start(); Thread.sleep(2000); service.signalAll(); } }
begin awaitA 时间为: 1462628140485 ThreadName=AA begin awaitA 时间为: 1462628140487 ThreadName=BB signal 时间为:1462628142485 end awaitA 时间为: 1462628142485 ThreadName=AA end awaitA 时间为: 1462628142485 ThreadName=BB |
public class MyService { private Lock lock = new ReentrantLock(); //使用多个Condition可以单独唤醒部分线程!!! private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); public void awaitA() { try { lock.lock(); System.out.println(" begin awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); conditionA.await(); System.out.println(" end awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void awaitB() { try { lock.lock(); System.out.println(" begin awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); conditionB.await(); System.out.println(" end awaitA 时间为: " + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signalAll_A() { try { lock.lock(); System.out.println("signal 时间为:" + System.currentTimeMillis()); conditionA.signalAll(); } finally { lock.unlock(); } } public void signalAll_B() { try { lock.lock(); System.out.println("signal 时间为:" + System.currentTimeMillis()); conditionB.signalAll(); } finally { lock.unlock(); } } }两个自定义的线程同上
public class Run { public static void main(String[] args) throws InterruptedException { MyService service = new MyService(); MyThread1 a = new MyThread1(service); a.setName("AA"); a.start(); MyThread2 b = new MyThread2(service); b.setName("BB"); b.start(); Thread.sleep(2000); service.signalAll_A(); //这里只唤醒线程A } }
begin awaitA 时间为: 1462629180458 ThreadName=BB begin awaitA 时间为: 1462629180469 ThreadName=AA signal 时间为:1462629182457 end awaitA 时间为: 1462629182457 ThreadName=AA |