锁的理解
锁产生于多线程并发应用,其作用是解决共享对象的同步同时也可以控制线程的行为。我认为锁不仅仅限于synchronize,ReentrantLock,ReadWriteLock.同时也包括CountDownLack, FutureTask, Semaphore, CyclicBarrier, Exchanger这些平时接触不多的并发控制类。后者经常会用在控制线程的运行行为。
1.
CountDownLack 这种锁经常用来控制多个线程同时启动,并且能够及时感知这些线程是否全部运行结束。举例如下:
例子中m_begin用来为那10个线程发送启动指令,当m_begin.countDown()时,10个线程同时启动。同时m_end.await()这些线程结束的好消息。
/** * @filename CountDownLaunchTest.java * @date 2014-11-14 */ package lock; import java.util.concurrent.CountDownLatch; public class CountDownLatchTest { public static void main(String[] args) { new CountDownLatchTest(10).runAll(); } private int m_threadNum = 10; private CountDownLatch m_begin = null; private CountDownLatch m_end = null; CountDownLatchTest(int threadNum) { if(threadNum>0) m_threadNum = threadNum; m_begin = new CountDownLatch(1); m_end = new CountDownLatch(m_threadNum); } public void runAll() { for(int i=0; i<m_threadNum; i++) { new InnerThread(String.valueOf(i)).start(); } m_begin.countDown(); try { m_end.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("all thread finished"); } private class InnerThread extends Thread { private final String name; InnerThread(String threadName) { name = threadName; System.out.println(name+" inited"); } @Override public void run() { try { //!!!!!注意是await,不是wait m_begin.await(); Thread.currentThread().sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } m_end.countDown(); System.out.println(name+" finished"); } } }
2.FutureTask 这种锁可以获取一个线程任务的运行结果,也就是说我们有个任务需要启动一个线程进行处理,同时也需要得到这个线程的返回结果时,用这个锁比较好用。
/** * @filename FutureTaskTest.java * @date 2014-11-14 */ package lock; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class FutureTaskTest { public static void main(String[] args) { new FutureTaskTest().test(); } public void test() { FutureTask<Integer> futureTask = new FutureTask<Integer>(new InnerRunnable()); futureTask.run(); try { int result = futureTask.get(); System.out.println(result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { //所有异常(除InterruptedException)均会封装成ExecutionException异常而抛出 e.printStackTrace(); } } private class InnerRunnable implements Callable<Integer> { public Integer call() throws Exception { try { Thread.sleep(3000); // throw new IllegalStateException(); } catch (InterruptedException e) { e.printStackTrace(); return -1; } return 0; } } }
3.
Semaphore,信号量,其经常用在线程池数量的控制或者队列大小的控制上,根据预先设定好的数值,然后有线程来acquire()和release(),当申请的次数大于预设值时将阻塞,直到其他线程释放资源。
/** * @filename SemaphoreTest.java * @date 2014-11-14 */ package lock; import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.Semaphore; public class SemaphoreTest { public static void main(String[] args) { SemaphoreTest test = new SemaphoreTest(); test.init(10); test.releaseNumToPool(1); test.getNumFromPool(); test.releaseNumToPool(11); } //通常用在连接池里面,用来限制申请连接的数目。 private Semaphore sem = new Semaphore(0); private final ConcurrentSkipListSet<Integer> m_numPool = new ConcurrentSkipListSet<Integer>(); public void init(int size) { for(int i=1; i<=size; i++) releaseNumToPool(i); } public Integer getNumFromPool() { try { sem.acquire(); } catch (InterruptedException e) { e.printStackTrace(); }; if(m_numPool.isEmpty()) return 0; return m_numPool.first(); } public void releaseNumToPool(Integer num) { if(!m_numPool.contains(num)) { m_numPool.add(num); sem.release(); } } }
4.
CyclicBarrier, 与CountDownLack和FutureTask不通的是,这种锁可以循环的使用,其用来规范线程任务的运行后行为,也就是当设置此锁有,多个线程运行完后,均会等在此锁上,当最后一个线程运行到此锁时,大家才继续运行。这个锁目前我能想到应用场景的地方不多,或许可以用在某些需要拼装工作同时拼装的场景里面吧。
/** * @filename CyclicBarrierTest.java * @date 2014-11-14 */ package lock; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrierTest test = new CyclicBarrierTest(10); for(int i=0; i<5; i++) test.startOnce(); } private CyclicBarrier m_barrier; private final Object lock = new Object(); public CyclicBarrierTest(int barrierSize) { m_barrier = new CyclicBarrier(barrierSize, new Runnable() { public void run() { synchronized (lock) { lock.notify(); } System.out.println("all thread run completed"); } }); } public void startOnce() { for(int i=1,size=m_barrier.getParties(); i<=size; i++) { InnerThread thread = new InnerThread(i*1000, String.valueOf(i)); thread.start(); } synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } private class InnerThread extends Thread { private long m_waitTime = 0; private String m_name; public InnerThread(long waitTime, String threadName) { if(waitTime>0) m_waitTime = waitTime; m_name = threadName; } @Override public void run() { try { Thread.sleep(m_waitTime); System.out.println(m_name+" waited "+m_waitTime); m_barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(m_name+" completed"); } } }
5.
Exchanger,其与SynchronizeQueue有相似之处,SynchronizeQueue是单向的,Exchanger是双向的。也就是说当两个线程运行到Exchanger时,双方均会将自己的数据交换给对方。目前我也没有想到很好的应用。
/** * @filename ExchangerTest.java * @date 2014-11-14 */ package lock; import java.util.concurrent.Exchanger; public class ExchangerTest { public static void main(String[] args) { new ExchangerTest().start(); } private Exchanger<String> exchanger = new Exchanger<String>(); public void start() { new cargoThread().start(); new moneyThread().start(); } private class cargoThread extends Thread { String message = "cargo"; public void run() { System.out.println("cargo thread is producing cargo"); try { Thread.sleep(5000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("cargo thread begin to wait exchange"); try { message = exchanger.exchange(message); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("cargo thread exchange message "+message); } } private class moneyThread extends Thread { String message = "money"; public void run() { System.out.println("money thread begin to wait exchange"); try { message = exchanger.exchange(message); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("money thread exchange message "+message); } } }
相关推荐
在并发控制方面,《Java并发编程实战》可能会探讨不同类型的锁,如互斥锁(Mutex)、读写锁(ReadWriteLock)、乐观锁和悲观锁等,以及它们的应用场景和性能影响。作者可能会使用实例代码来演示如何在实际应用中使用...
在Java并发编程中,主要涉及以下几个关键知识点: 1. **线程与进程**:线程是程序执行的最小单元,一个进程中可以有多个线程同时执行。理解线程的概念和生命周期对于并发编程至关重要。 2. **线程安全**:当多个...
锁机制是Java并发编程中的另一大主题,包括内置锁(互斥锁)和显式锁(如`ReentrantLock`)。内置锁是`synchronized`关键字提供的,而显式锁提供了更细粒度的控制和更丰富的功能。书中可能还会讨论读写锁(`...
锁是Java并发编程中用于同步的关键工具。书中深入剖析了各种锁机制,如内置锁(也称为监视器锁),通过`synchronized`关键字实现。此外,还介绍了高级的锁接口`java.util.concurrent.locks`,如`ReentrantLock`,它...
在《Java并发编程实战》这本书中,作者深入浅出地介绍了Java 5.0和Java 6中新增的并发特性。这些特性旨在帮助开发者更高效、安全地编写多线程程序。书中通过实例解释了诸如`ExecutorService`、`Future`、`Callable`...
3. **锁**:Java并发库中的`java.util.concurrent.locks`包提供了更高级的锁机制,如可重入锁(`ReentrantLock`)、读写锁(`ReadWriteLock`)和条件变量(`Condition`),这些工具允许更灵活的控制并发访问。 4. **并发...
Java并发编程实践是Java开发中不可或缺的一个领域,它涉及到如何高效、正确地处理多线程环境中的任务。这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的...
通过学习《Java并发编程实践》,开发者将能够更好地理解和利用Java平台的并发特性,编写出更高效、更可靠的多线程应用程序。无论是初级开发者还是经验丰富的专业人员,都能从这本书中收获宝贵的并发编程知识。
Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...
"Java并发编程与实践"文档深入剖析了这一主题,旨在帮助开发者理解和掌握如何在Java环境中有效地实现并发。 并发是指在单个执行单元(如CPU)中同时执行两个或更多任务的能力。在Java中,这主要通过线程来实现,...
Java并发API包括了线程、锁、同步、并发容器等丰富的工具,使得开发者可以构建能够充分利用多核处理器性能的应用程序。本书详细介绍了这些主题,并提供了实例代码和实践建议。 首先,书中详细讨论了Java线程的创建...
《Java并发实战》是深入探讨Java编程中并发处理的一本技术书籍。在现代软件开发中,多线程和并发控制是提升程序性能的关键技术,尤其是在服务器端开发中尤为重要。Java作为一门成熟的编程语言,其在并发控制方面提供...
#### 一、Java并发概述 自Java诞生之初,其设计者就赋予了该语言强大的并发处理能力。Java语言内置了对线程和锁的支持,这使得开发者能够轻松地编写多线程应用程序。本文旨在帮助Java开发者深入理解并发的核心概念...
第四部分深入探讨了Java并发编程的高级主题,包括显式锁(如ReentrantLock)、原子变量(Atomic类)、非阻塞算法以及自定义同步组件的开发。这些高级主题帮助开发者解决复杂并发场景下的问题,实现更高层次的并发...
阻塞队列(BlockingQueue)是Java并发工具包中的一个重要组成部分,它能够保证在队列为空时取元素的操作会等待队列变为非空,而在队列满时插入元素的操作会等待队列中有空余空间。常见的阻塞队列实现有...
在《java并发库高级应用源码--张孝祥》中,我们将会深入探讨Java中的线程管理和并发控制策略,这对于我们理解和优化多线程程序至关重要。 首先,Java中的`Thread`类是实现并发的基础,它代表了一个独立的执行线程。...
Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...