/* Eratosthenes' Sieve */ /* Multithreaded implementation */ /* File Eratosthenes.java */ /* Main program */ public class Eratosthenes{ public static void main(String[] args) { Queue q = new Queue(); new Generator(q,1000).start(); new Sieve(q).start(); } } /* Definition of Item, the class of the active components of the system */ class Item extends Thread { protected Queue source; protected Queue destination; } /* Generator: generates all natural numbers from 2 to maximum */ class Generator extends Item { private int value; private int maximum; public void run(){ while (value < maximum) { destination.insert(value++); } destination.insert(0); // System.out.println("Generator terminated"); } Generator(Queue dst, int m){ destination = dst; value = 2; maximum = m; } } /* Filter: transmits only the numbers which are not multiple of factor */ class Filter extends Item { private int factor; public void run() { int n = source.pop(); while (n > 0) { if (n%factor != 0) { destination.insert(n); } n = source.pop(); } destination.insert(0); // System.out.print("Filter "); // System.out.print(factor); // System.out.println(" terminated"); } Filter(int f, Queue src, Queue dst) { factor = f; destination = dst; source = src; } } /* Sieve: when receives n, prints n and creates a new filter with factor = n */ class Sieve extends Item{ public void run() { int n = source.pop(); while (n > 0) { System.out.print(n); System.out.print(" "); Queue q = new Queue(); new Filter(n,source,q).start(); source = q; n = source.pop(); } // System.out.println("Sieve terminated"); } Sieve(Queue src){ source = src; } } /* --------------------------------------------------------- */ /* The next class defines the data structure "queue", which is used to transmit the numbers among the various items (generator, filters and sieve) of the system. The methods of Queue are synchronized so to avoid erroneous interleaving of actions when accessed by several (in our case, two) items */ class Queue { private class Element { int info; Element next; Element(int n) { info = n; next = null; } } private Element first; private Element last; Queue() { first = last = null; } public synchronized void insert(int n){ if (first == null) { first = last = new Element(n); notifyAll(); } else { last = last.next = new Element(n); } } public synchronized int pop(){ try { while (first == null) wait(); } catch (InterruptedException e) { return 1; // We could do a better treatment of the case } // of interruption, but it's not the object of the exercise int n = first.info; first = first.next; if (first == null) { last = null; } //this line is not necessary return n; } } /* --------------------------------------------------------- */