以前遇到一个面试题,一些农民往桶里放苹果,一些农民往桶里面拿苹果,当桶达到1000个苹果的时候不能再放了,当桶的个数少于5个的时候不能再拿了。这个例子用lock和condition可以很好的解决。condition有await方法和signal方法,当调用await方法的时候,会释放当前的锁,然后将当前线程放到condition的等待队列中。当调用signal方法时,会调用将condition等待队列中的第一个线程放到sync队列中,那样那个线程就可以继续竞争锁。Condition和object的wait,notify方法的区别是,同一个锁可以有多个条件控制。而object的wait方法则不能。
import sun.misc.Unsafe; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Created by Administrator on 8/3/14. */ public class Bucket<T> { private List<T> cache = new ArrayList<T>(); private ReentrantLock lock = new ReentrantLock(); private Condition putCondition = lock.newCondition(); private Condition getCondition = lock.newCondition(); private int capacity = 1000; private int minSize = 5; public Bucket(int capacity, int minSize) { if(minSize >= capacity){ throw new IllegalArgumentException("capacity must large than minSize!"); } this.capacity = capacity; this.minSize = minSize; } public void put(T object){ try{ lock.lock(); while (cache.size() == capacity){ putCondition.await(); } cache.add(object); getCondition.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public T get(){ T value = null; try{ lock.lock(); while (cache.size() <= minSize){ getCondition.await(); } System.out.println("Cache size:" + cache.size()); value = cache.remove(0); putCondition.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } return value; } static class Apple{ public String getKey() { return key; } public void setKey(String key) { this.key = key; } private String key; Apple(String key) { this.key = key; } } static class Provider implements Runnable{ private Bucket<Object> bucket; private String name; public Provider(Bucket<Object> bucket,String name) { this.bucket = bucket; this.name = name; } @Override public void run() { int index = 1; while (true){ Apple apple = new Apple(name + "-" + index++); bucket.put(apple); System.out.println("Add apple " + apple.getKey() + " to bucket"); } } } static class Consumer implements Runnable{ Bucket<Object> bucket; public Consumer(Bucket<Object> bucket) { this.bucket = bucket; } @Override public void run() { while (true){ Apple apple = (Apple) bucket.get(); System.out.println("Get apple " + apple.getKey() + " from bucket"); } } } public static void main(String[] args){ Bucket<Object> bucket = new Bucket<Object>(100,5); for(int i =0;i < 2;i++){ new Thread(new Provider(bucket,"Provider" + i)).start(); } for(int i =0;i < 5;i++){ new Thread(new Consumer(bucket)).start(); } } }
改进版,put和take可以同时运行。模拟LinkedBlockQueue
/** * Created by Administrator on 8/10/14. */ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.misc.Unsafe; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Created by Administrator on 8/3/14. */ public class BucketEx<T> { static Logger logger = LoggerFactory.getLogger(BucketEx.class); private ReentrantLock takeLock = new ReentrantLock(); private ReentrantLock putLock = new ReentrantLock(); private Condition notFull = putLock.newCondition(); private Condition notEmpty = takeLock.newCondition(); private Node<T> head, tail; private AtomicInteger count = new AtomicInteger(0); private int capacity = 1000; private int minSize = 5; class Node<T> { Node<T> next; T item; Node(T item) { this.item = item; } } public BucketEx(int capacity, int minSize) { if (minSize >= capacity) { throw new IllegalArgumentException("capacity must large than minSize!"); } this.capacity = capacity; this.minSize = minSize; head = tail = new Node<T>(null); } public T dequeue() { Node h = head; Node<T> first = h.next; h.next = h; T item = first.item; first.item = null; head = first; return item; } public void enqueue(T item) { tail = tail.next = new Node<T>(item); } public void signalNotEmpty() { takeLock.lock(); try{ notEmpty.signal(); }finally { takeLock.unlock(); } } public void signalNotFull() { putLock.lock(); try{ notFull.signal(); }finally { putLock.unlock(); } } public void put(T object) throws InterruptedException { putLock.lockInterruptibly(); int c = -1; try { while (count.get() >= capacity) { notFull.await(); } enqueue(object); c = count.getAndIncrement(); logger.info("put " + object.toString() + " size" + c); if (c < capacity) { notFull.signal(); } }finally { putLock.unlock(); } if (c == minSize) { signalNotEmpty(); } } public T get() throws InterruptedException { T item = null; takeLock.lockInterruptibly(); int c = -1; try { while (count.get() <= minSize) { notEmpty.await(); } item = dequeue(); c = count.getAndDecrement(); logger.info("take " + item.toString() + " size" + c); if (c > minSize) { notEmpty.signal(); } } finally { takeLock.unlock(); } if (c == capacity) { signalNotFull(); } return item; } static class Apple { public String getKey() { return key; } public void setKey(String key) { this.key = key; } private String key; Apple(String key) { this.key = key; } @Override public String toString() { return "Apple{" + "key='" + key + '\'' + '}'; } } static class Provider implements Runnable { private BucketEx<Object> bucket; private String name; public Provider(BucketEx<Object> bucket, String name) { this.bucket = bucket; this.name = name; } @Override public void run() { int index = 1; while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } Apple apple = new Apple(name + "-" + index++); try { bucket.put(apple); } catch (InterruptedException e) { e.printStackTrace(); } } } } static class Consumer implements Runnable { BucketEx<Object> bucket; String name; public Consumer(BucketEx<Object> bucket,String name) { this.bucket = bucket; this.name = name; } @Override public void run() { while (true) { try { Apple apple = (Apple) bucket.get(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { BucketEx<Object> bucket = new BucketEx<Object>(1000, 5); for (int i = 0; i < 1; i++) { new Thread(new Provider(bucket, "Provider" + i), "Provider" + i).start(); } Thread.sleep(10000); for (int i = 0; i < 5; i++) { new Thread(new Consumer(bucket,"Customer" + i),"Customer" + i).start(); } } }
相关推荐
- **同步机制**:synchronized关键字、Lock接口(ReentrantLock、Condition)的使用,以及死锁的概念。 - **并发容器**:如ConcurrentHashMap、BlockingQueue、ThreadPoolExecutor等在多线程环境下的应用。 4. **...
Java是世界上最流行的编程语言之一,尤其在企业级应用开发领域占据主导地位。本文将深入探讨Java中的并发和...Java复习笔记中应该涵盖了这些内容的详细解释和实例,通过深入学习,你可以进一步巩固和提升自己的技能。
2. **并发控制**:Java提供了多种并发控制工具,如`synchronized`关键字、`wait()`/`notify()`、`Lock`接口(包括`ReentrantLock`可重入锁)及其相关的`Condition`条件对象。 3. **原子操作**:`java.util....
这份“JAVA复习资料”显然旨在帮助学习者巩固和提升Java编程技能,为备考或者项目开发提供支持。下面,我们将深入探讨Java的核心概念和技术。 一、Java基础 1. 类与对象:Java是一种面向对象的语言,类是对象的模板...
《Java语言程序设计》是Java编程领域的一本经典教材,其第八版的源码资源包含例题、习题以及复习题的源代码,是学习和深入理解Java编程的重要辅助资料。这些源码由西安电子科技大学的李娜翻译,保证了内容的专业性和...
4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...
线程同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和Condition接口的使用,都是多线程编程中的重点。 6. **IO流**:Java的IO流分为字节流和字符流,以及输入流和输出流。了解...
线程同步是多线程编程中的关键,包括synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和Condition对象。此外,还有死锁、活锁和饥饿等并发问题需要理解和避免。 接下来是EJB(Enterprise ...
4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...
11.2.1 lock、readwritelock与condition 349 11.2.2 使用executor 357 11.2.3 并行collection简介 370 11.3 重点复习 373 11.4 课后练习 375 chapter12 通用api 377 12.1 日志 378 12.1.1 日志api简介...
Java编程语言是当今软件开发领域中的重要工具,尤其在...通过对这些知识点的复习和理解,考生可以更好地准备四川大学Java期末考试,提升自己的编程技能。同时,这些知识点也是Java程序员在实际工作中必须掌握的基础。
Java提供锁(lock)、条件(condition)、wait、notify和notifyAll等机制来实现线程间的通信。例如,synchronized关键字和ReentrantLock类可以用来创建互斥锁,condition对象可用于线程间的协调,而wait和notify/...
- Lock接口:熟悉ReentrantLock、Condition等锁机制,了解公平锁和非公平锁的概念。 - CountDownLatch、CyclicBarrier、Semaphore等同步工具类的应用。 4. **设计模式**: - 常见的设计模式如单例、工厂、观察者...
- 掌握线程同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和Condition接口。 5. **内存管理与垃圾回收** - 理解Java内存模型,包括堆、栈、方法区、程序计数器等。 - 垃圾...
Java提供了多种同步工具,如显式锁Lock、条件变量Condition、wait/notify/notifyAll机制等,用于线程间的通信和协作。 无锁编程(Lock-free)是一种实现并发程序设计的技术,它避免使用传统的锁机制,而是通过原子...
多线程是Java的一个强项,面试中可能会讨论线程同步机制,如synchronized关键字、volatile变量、Lock接口和Condition,以及死锁、活锁和饥饿等问题。 反射是Java的动态特性,允许在运行时检查类的信息并操作类的...
包括`Lock`、`Condition`、`wait()`、`notify()`和`notifyAll()`。`Lock`提供了比`synchronized`更细粒度的锁定控制,`Condition`允许在特定条件下释放锁。`wait()`、`notify()`和`notifyAll()`是基于对象监视器的...