if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
生产者消费者模式要保证的是当缓冲区满的时候生产者不再生产对象,当缓冲区空时,消费者不再消费对象。实现机制就是当缓冲区满时让生产者处于等待状态,当缓冲区为空时让消费者处于等待状态。当生产者生产了一个对象后会唤醒消费者,当消费者消费一个对象后会唤醒生产者。
三种种实现方式:wait 和 notify、await 和 signal、BlockingQueue。
//wait和notify
import java.util.LinkedList;
public class StorageWithWaitAndNotify {
private final int MAX_SIZE = 10;
private LinkedList list = new LinkedList();
public void produce() {
synchronized (list) {
while (list.size() == MAX_SIZE) {
System.out.println(“仓库已满:生产暂停”);
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(new Object());
System.out.println(“生产了一个新产品,现库存为:” + list.size());
list.notifyAll();
}
}
public void consume() {
synchronized (list) {
while (list.size() == 0) {
System.out.println(“库存为0:消费暂停”);
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.remove();
System.out.println(“消费了一个产品,现库存为:” + list.size());
list.notifyAll();
}
}
}
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class StorageWithAwaitAndSignal {
private final int MAX_SIZE = 10;
private ReentrantLock mLock = new ReentrantLock();
private Condition mEmpty = mLock.newCondition();
private Condition mFull = mLock.newCondition();
private LinkedList mList = new LinkedList();
public void produce() {
mLock.lock();
while (mList.size() == MAX_SIZE) {
System.out.println(“缓冲区满,暂停生产”);
try {
mFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mList.add(new Object());
System.out.println(“生产了一个新产品,现容量为:” + mList.size());
mEmpty.signalAll();
mLock.unloc
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
k();
}
public void consume() {
mLock.lock();
while (mList.size() == 0) {
System.out.println(“缓冲区为空,暂停消费”);
try {
mEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mList.remove();
System.out.println(“消费了一个产品,现容量为:” + mList.size());
mFull.signalAll();
mLock.unlock();
}
}
import java.util.concurrent.LinkedBlockingQueue;
public class StorageWithBlockingQueue {
private final int MAX_SIZE = 10;
private LinkedBlockingQueue list = new LinkedBlockingQueue(MAX_SIZE);
public void produce() {
if (list.size() == MAX_SIZE) {
System.out.println(“缓冲区已满,暂停生产”);
}
try {
list.put(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“生产了一个产品,现容量为:” + list.size());
}
public void consume() {
if (list.size() == 0) {
System.out.println(“缓冲区为空,暂停消费”);
}
try {
list.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“消费了一个产品,现容量为:” + list.size());
}
}
final 可以修饰类、变量和方法。修饰类代表这个类不可被继承。修饰变量代表此变量不可被改变。修饰方法表示此方法不可被重写 (override)。
finally 是保证重点代码一定会执行的一种机制。通常是使用 try-finally 或者 try-catch-finally 来进行文件流的关闭等操作。
finalize 是 Object 类中的一个方法,它的设计目的是保证对象在垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK 9已经被标记为 deprecated。
Java 中常见的单例模式实现有这么几种:饿汉式、双重判断的懒汉式、静态内部类实现的单例、枚举实现的单例。 这里着重讲一下双重判断的懒汉式和静态内部类实现的单例。
双重判断的懒汉式:
public class SingleTon {
//需要注意的是volatile
private static volatile SingleTon mInstance;
private SingleTon() {
}
public static SingleTon getInstance() {
if (mInstance == null) {
synchronized (SingleTon.class) {
if (mInstance == null) {
mInstance=new SingleTon();
}
}
}
return mInstance;
}
}
双重判断的懒汉式单例既满足了延迟初始化,又满足了线程安全。通过 synchronized 包裹代码来实现线程安全,通过双重判断来提高程序执行的效率。这里需要注意的是单例对象实例需要有 volatile 修饰,如果没有 volatile 修饰,在多线程情况下可能会出现问题。原因是这样的,mInstance=new SingleTon()
这一句代码并不是一个原子操作,它包含三个操作:
我们知道 JVM 会发生指令重排,正常的执行顺序是1-2-3
,但发生指令重排后可能会导致1-3-2
。我们考虑这样一种情况,当线程 A 执行到1-3-2
的3步骤暂停了,这时候线程 B 调用了 getInstance,走到了最外层的if判断