Java中多线程通信实例:生产者消费者模式

线程间的通信:其实就是多个线程在操作同一个资源,但是操作的动作不同

当某个线程进入synchronized块后,共享数据的状态不一定满足该线程的需要,需要其他线程改变共享数据的状态后才能运行,而由于当时线程对共享资源时独占的,它必须解除对共享资源的锁定的状态,通知其他线程可以使用该共享资源。

Java中的 wait(),notify(),notifyAll()可以实现线程间的通信。

生产者–消费者问题是典型的线程同步和通信问题

  • 生产者生产出产品,消费者去购买产品
  • 创建三个线程,一个主控线程,一个生产者线程,一个消费者线程,
  • 创建一个堆栈 Stack,生成线程生成的产品放置到堆栈中,然后消费者线程在堆栈中取走产品

【实际问题】异步实现字符串的拼接

设定条件如下:

有两个线程,Producer线程负责字符串的读取,Consumer线程负责字符串的拼接,当输入字符串开头为‘0’时,退出Producer和Consumer线程,并将拼接后的字符串打印出来。

[例]

输入:

My country↓
is ↓
awesome↓
0↓

输出:

My country is awesome

/**
 * 创建一个堆栈 Stack,生产者线程生成的产品放置到堆栈中,然后消费者线程在堆栈中取走产品
 * Created by ZhangJun on 2017/10/21.
 */

public class ProductStack {

    private String product;
    private boolean available = false;

    /**
     * 生成产品的方法
     *
     * @param product
     */
    public synchronized void setProduct(String product) {
        // 如果堆栈满了,调用wait()等待消费者取走产品
        while (available) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.product = product;
        this.available = true;
        // 生产者被唤醒后,开始放置产品到堆栈中
        this.notifyAll();
        System.out.println("生产者生产产品:" + product);
    }

    /**
     * 获取产品的方法
     *
     * @return product
     */
    public synchronized String getProduct() {
        // 如果堆栈是空的,调用wait()等待生产者生产产品
        while (!available) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.available = false;
        // 消费者被唤醒后,开始从堆栈取走产品,然后通知生产者继续生产产品
        this.notifyAll();
        System.out.println("消费者消费产品:" + product);
        return product;
    }

}
/**
 * 生产者类
 * Created by ZhangJun on 2017/10/21.
 */

public class Producer extends Thread {

    private ProductStack mProductStack;

    public Producer(ProductStack ps) {
        this.mProductStack = ps;
    }

    @Override
    public void run() {
        //生产线程
        List list = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        String nextLine = scanner.nextLine();
        while (true) {
            if (!nextLine.startsWith("0")) {
                list.add(nextLine);
                nextLine = scanner.nextLine();
            } else {
                list.add(nextLine);
                break;
            }
        }
        System.out.println("list size = " + list.size());
        for (String aList : list) {
            mProductStack.setProduct(aList);
        }
    }
}
/**
 * 消费者类
 * Created by ZhangJun on 2017/10/21.
 */

public class Consumer extends Thread {

    private ProductStack mProductStack;

    public Consumer(ProductStack ps) {
        this.mProductStack = ps;
    }

    @Override
    public void run() {
        //消费线程
        StringBuilder products = new StringBuilder();
        while (true) {
            String product = mProductStack.getProduct();
            if (product.startsWith("0")) {
                break;
            }
            products.append(product + " ");
        }
        System.out.println("消费者消费的所有产品:" + products);
    }
}
/**
 * 主控线程 main
 * Created by ZhangJun on 2017/10/21.
 */

public class Main {

    public static void main(String[] args) {
        ProductStack productStack = new ProductStack();
        new Producer(productStack).start();
        new Consumer(productStack).start();
    }
}

你可能感兴趣的:(Java,进阶,java,多线程,通信,生产者,消费者)