多线程-单生产单消费模型
创建资源对象,提供保存和取出方法(使用synchronized代码块实现)
/**
* Created by shaoqinghua on 2018/5/3.
* 定义一个负责保存和取出的资源类
*/
public class Resource {
/**
* 定义成员变量,充当保存和取出的容器
*/
private Object[] objs = new Object[1];
/**
* 定义一个同步的锁对象
*/
private Object lock = new Object();
/**
* 保存数据
*/
public void save(Object obj) {
synchronized (lock) {
if (objs[0] != null) {
//存在数据,保存线程不能执行保存操作,需要等待
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
objs[0] = obj;
System.out.println(Thread.currentThread().getName() + " 正在保存的数据:" + objs[0]);
//在生产者保存完数据后,需要唤醒消费线程
lock.notify();
}
}
/**
* 取出数据
*/
public void get() {
synchronized (lock) {
if (objs[0] == null) {
//没有数据,无法取出,需要等待
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "正在取出的数据:::::::" + objs[0]);
objs[0] = null;
//消费结束,需要通知生产者线程
lock.notify();
}
}
}
创建生产者任务类
/**
* Created by shaoqinghua on 2018/5/3.
*/
public class Productor implements Runnable {
private Resource r;
public Productor(Resource r) {
this.r = r;
}
@Override
public void run() {
//给资源仓库保存数据
while (true) {
r.save("汽车");
}
}
}
创建消费者任务类
/**
* Created by shaoqinghua on 2018/5/3.
*/
public class Consumer implements Runnable {
private Resource r;
public Consumer(Resource r) {
this.r = r;
}
@Override
public void run() {
//从资源仓库取出数据
while (true) {
r.get();
}
}
}
测试类
/**
* Created by shaoqinghua on 2018/5/3.
* 测试单生产单消费
*/
public class ThreadTest {
public static void main(String[] args) {
//创建资源对象
Resource r = new Resource();
//创建线程任务对象
Productor pro = new Productor(r);
Consumer con = new Consumer(r);
//创建生产和消费的线程对象
Thread t = new Thread(pro);
Thread t2 = new Thread(con);
//启动线程
t.start();
t2.start();
}
}
另外,Resource资源类也可使用JDK5之后的Lock和Condition实现
/**
* Created by shaoqinghua on 2018/5/3.
* 定义一个负责保存和取出的资源类
*/
public class Resource {
/**
* 定义成员变量,充当保存和取出的容器
*/
private Object[] objs = new Object[1];
/**
* 定义JDK5之后的Lock锁
*/
private Lock loc = new ReentrantLock();
/**
* 定义监视生产者线程的等待和唤醒对象
*/
private Condition proCon = loc.newCondition();
/**
* 定义监视消费者线程的等待和唤醒对象
*/
private Condition conCon = loc.newCondition();
/**
* 保存数据
*/
public void save(Object obj) {
//手动获取锁对象
loc.lock();
try {
if (objs[0] != null) {
//存在数据,保存线程不能执行保存操作,需要等待
try {
proCon.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
objs[0] = obj;
System.out.println(Thread.currentThread().getName() + " 正在保存的数据:" + objs[0]);
//在生产者保存完数据后,需要唤醒消费线程
conCon.signal();
} finally {
//手动释放锁对象
loc.unlock();
}
}
/**
* 取出数据
*/
public void get() {
//手动获取锁对象
loc.lock();
try {
if (objs[0] == null) {
//没有数据,无法取出,需要等待
try {
conCon.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "正在取出的数据:::::::" + objs[0]);
objs[0] = null;
//消费结束,需要通知生产者线程
proCon.signal();
} finally {
//手动释放锁对象
loc.unlock();
}
}
}
文章来源:
Author:LaravelShao
link:https://my.oschina.net/LaravelShao/blog/1807245
下一篇:多线程-单例模式安全问题