多线程-单生产单消费模型

创建资源对象,提供保存和取出方法(使用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