单例模式
- 之前有一个博客简述了单例模式,这里就不具体介绍了
- 单例模式的实现方式:懒汉式和饿汉式
- 其中,懒汉式是线程不安全的,当有多条线程同时访问单例对象时,则会出现多线程临界资源问题
多线程下的懒汉式
package waking.test.xcms;
import java.util.HashSet;
public class Demo01 {
static HashSet<Kind> hs = new HashSet<Kind>();
static Runnable r = new Runnable() {
@Override
public void run() {
Kind kind = Kind.getKindInstance();
hs.add(kind);
}
};
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(r);
t.start();
}
System.out.println(hs);
}
}
class Kind {
private static Kind kind = null;
private Kind() {
}
public static Kind getKindInstance() {
if(kind==null) {
kind = new Kind();
}
return kind;
}
}
多线程下的饿汉式
package waking.test.xcms;
import java.util.HashSet;
public class Demo02 {
static HashSet<Hungry> hs = new HashSet<Hungry>();
static Runnable r = new Runnable() {
@Override
public void run() {
Hungry h = Hungry.getHungryInstance();
hs.add(h);
}
};
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(r);
t.start();
}
System.out.println(hs);
}
}
class Hungry{
private static Hungry hungry = new Hungry();
private Hungry() {
}
public static Hungry getHungryInstance() {
return hungry;
}
}
生产者、消费者模式
原理
- 它描述的是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者可以从仓库中取走产品,解决生产者、消费者问题,我,们需要采用某种机制保护生产者和消费者的同步
- 同步的问题核心在于:如何保证同一个资源被多个线程并发访问时的完整性,常用的方法就是加锁,保证资源在任意时刻只被一份线程访问
实现
- 方式一:采用wait()、notify()和notifyAll()方法
wait():当缓冲区已满或空时,生产者、消费者线程停止自己的执行,放弃锁,使用自己处于等待状态,让其他线程执行
说明:
a.是Object的方法
b.调用方式:对象.wait();
c.表示释放、对象这个锁标记,然后在锁外面等待(对比sleep(),sleep()是抱着锁休眠的)
d.等待,必须放到同步代码中执行
notify():当生产者、消费者向缓冲区放入、取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态
说明:
a.是object的方法
b.调用方式:对象.notify();
c.表示唤醒对象所标记外边在等待的一个线程
notifyAll():全部唤醒
a.是objectde 方法
b.调用方式:对象.notifyAll()
c.表示唤醒对象所标记外边等待的所有线程
package waking.test.xcms;
public class Demo03 {
static boolean shouldProduct = true;
static class Productor implements Runnable{
private Product product;
public Productor(Product product) {
this.product = product;
}
@Override
public void run() {
while(true) {
synchronized ("") {
if(shouldProduct) {
this.product.setName("waking");
System.out.println("生产者:"+Thread.currentThread().getName()+"生产了,一个"+this.product);
shouldProduct=false;
"".notifyAll();
}else {
try {
"".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
static class Consumer implements Runnable{
private Product P;
public Consumer(Product p) {
this.P = p;
}
@Override
public void run() {
while(true) {
synchronized ("") {
if(shouldProduct) {
try {
"".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println("消费者:"+Thread.currentThread().getName()+"消费了,一个产品"+this.P);
shouldProduct=true;
"".notifyAll();
}
}
}
}
}
public static void main(String[] args) {
Product p = new Product();
Productor por = new Productor(p);
Thread t = new Thread(por,"A");
Thread t2 = new Thread(por,"B");
Thread t3 = new Thread(por,"C");
Thread t4 = new Thread(por,"D");
t.start();
t2.start();
t3.start();
t4.start();
Consumer c = new Consumer(p);
Thread t5 = new Thread(c,"a");
Thread t6 = new Thread(c,"b");
Thread t7 = new Thread(c,"c");
Thread t8 = new Thread(c,"d");
t5.start();
t6.start();
t7.start();
t8.start();
}
}
class Product{
private String name;
int id;
public String getName() {
id--;
return name;
}
public void setName(String name) {
this.name = name;
id++;
}
@Override
public String toString() {
return "Product [name=" + name + ", id=" + id + "]";
}
}
- 采用ReentrantLock类中的newCondition()方法结合Condition类中的await()、signal()和signalAll()方法
package waking.test.xcms;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Demo04 {
static boolean flage = true;
static ReentrantLock lock = new ReentrantLock();
static Condition c1 = lock.newCondition();
static Condition c2 = lock.newCondition();
static class Pro implements Runnable{
private S s;
public Pro(S s) {
super();
this.s = s;
}
@Override
public void run() {
while(true) {
try {
lock.lock();
if (flage) {
this.s.setName("waking");
System.out.println("生产者:" + Thread.currentThread().getName() + "生产了" + this.s);
flage = false;
c2.signalAll();
} else {
try {
c1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}
}
static class Con implements Runnable{
private S ss;
public Con(S ss) {
super();
this.ss = ss;
}
@Override
public void run() {
while(true) {
try {
lock.lock();
if (flage) {
try {
c2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("消费者:" + Thread.currentThread().getName() + "消费了" + this.ss);
flage = true;
c1.signalAll();
}
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
S s = new S();
Pro p = new Pro(s);
new Thread(p,"A").start();
new Thread(p,"B").start();
new Thread(p,"C").start();
new Thread(p,"D").start();
Con c = new Con(s);
new Thread(c, "a").start();
new Thread(c, "b").start();
new Thread(c, "c").start();
new Thread(c, "d").start();
}
}
}
class S{
private String name;
int id;
public String getName() {
id--;
return name;
}
public void setName(String name) {
this.name = name;
id++;
}
@Override
public String toString() {
return "S [name=" + name + ", id=" + id + "]";
}
}
以上是多线程下的单例模式、生产者、消费者模式的情况,感谢您的观看