Saturday, September 6, 2014

9. A Worked Example Using Low-Level Synchronization

Java Multithreading: Low-Level Producer-Consumer
In this tutorial we’ll look at how to implement the producer-consumer pattern using “low level” techniques; namely, wait, notify and synchronized. This isn’t the best way to implement a producer-consumer pattern in Java (see tutorial 7 for the best way); but this tutorial will help you to understand how to use wait and notify.

Code For This Tutorial
The main program just runs the produce() and consume() methods in different threads.
import java.util.LinkedList;
import java.util.Random;

class Processor {

    private LinkedList<Integer> list = new LinkedList<Integer>();
    private final int LIMIT = 10;
    private Object lock = new Object();

    public void produce() throws InterruptedException {

        int value = 0;

        while (true) {

            synchronized (lock) {
                
                while(list.size() == LIMIT) {
                    lock.wait();
                }
                
                list.add(value++);
                lock.notify();
            }

        }
    }

    public void consume() throws InterruptedException {
        
        Random random = new Random();

        while (true) {

            synchronized (lock) {
                
                while(list.size() == 0) {
                    lock.wait();
                }
                
                System.out.print("List size is: " + list.size());
                int value = list.removeFirst();
                System.out.println("; value is: " + value);
                lock.notify();
            }
            
            Thread.sleep(random.nextInt(1000));
        }
    }
}

Output:
List size is: 2; value is: 0
List size is: 10; value is: 1
List size is: 10; value is: 2
List size is: 10; value is: 3
List size is: 10; value is: 4
List size is: 10; value is: 5
List size is: 10; value is: 6
List size is: 10; value is: 7
List size is: 10; value is: 8

The main program (just creates and runs two threads):

public class App {

    public static void main(String[] args) throws InterruptedException {

        final Processor processor = new Processor();

        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.consume();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
    }

}

No comments:

Post a Comment