Java Thread Series (10) Producer Consumer Mode

Java Thread Series (10) Producer Consumer Mode

The producer-consumer problem is a classic case of a multi-threaded synchronization problem. The problem describes what happens when two threads sharing a fixed-size buffer—the so-called "producers" and "consumers"—are actually running.

1. Signal light method

The semaphore method actually ensures that only one thread is operating data at the same time, and notifies other threads after the operation is completed, thereby avoiding deadlock.

(1) Producer

public class Producer implements Runnable {

    private Data data;

    public Producer(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            data.produce(String.format("product-%s", i));
        }
    }
}

(2) Consumers

public class Consumer implements Runnable {
    private Data data;

    public Consumer(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        while (true) {
            data.consume();
        }
    }
}

(3) Data

public class Data {

    private String data;

    // flag = true  生产者生产,消费者等待,生产完毕后通知消费者消费
    // flag = false 消费者消费,生产者等待,消费完毕后通知生产者生产
    private boolean flag = true;

    public synchronized void consume() {
        if (flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                ;
            }
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            ;
        }

        notify();
        System.out.println("消费者消费:" + getData());
        flag = true;
    }

    public synchronized void produce(String data) {
        if (!flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                ;
            }
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            ;
        }

        notify();
        System.out.println("生产者生产:" + data);
        setData(data);
        flag = false;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}

(4) Test

public static void main(String[] args) {
    Data data = new Data();
    new Thread(new Producer(data)).start();
    new Thread(new Consumer(data)).start();
}

2. Container method

(1) Producter

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Producter implements Runnable {

    private BlockingQueue<Data> data;
    //用于生成id
    private static AtomicInteger count = new AtomicInteger(0);

    public Producter(BlockingQueue<Data> data) {
        this.data = data;
    }

    public Producter() { }

    @Override
    //生产者生产数据
    public void run() {
        try {
            Thread.sleep(2000);
            int id = count.incrementAndGet();
            if (!this.data.offer(new Data(id, "data-" + id), 2, TimeUnit.SECONDS)) {
                System.out.printf("%s生产:data-%s失败\n", Thread.currentThread().getName(), id);
            } else {
                System.out.printf("%s生产:data-%s\n", Thread.currentThread().getName(), id);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

(2) Consumer

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {

    private BlockingQueue<Data> data;

    public Consumer(BlockingQueue<Data> data) {
        this.data = data;
    }
    public Consumer() { }

    @Override
    //消费者消费数据
    public void run() {
        Data d = null;
        try {
            d = this.data.take();
            System.out.printf("%s消费:%s\n", Thread.currentThread().getName(), d.getName());

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Data {
    private int id;
    private String name;
}

(3) Test

LinkedBlockingQueue<Data> data = new LinkedBlockingQueue<Data>();

Producter p1 = new Producter(data);
Producter p2 = new Producter(data);
Producter p3 = new Producter(data);

Consumer c1 = new Consumer(data);
Consumer c2 = new Consumer(data);
Consumer c3 = new Consumer(data);

ExecutorService pool = Executors.newCachedThreadPool();
pool.execute(p1);
pool.execute(p2);
pool.execute(p3);
pool.execute(c1);
pool.execute(c2);
pool.execute(c3);
pool.shutdown();

Record a little bit every day. Content may not be important, but habits are!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325382214&siteId=291194637