Search code examples
javamultithreadingwaitsynchronizednotify

Synchronized Threads in 1 Class


I have been searching for a way to use multiple threads and synchronization successfully. I've tried using wait() and notify(), but my threads still don't synchronize. I have a bigger project, but in a nutshell, I need it to run a thread with a setter method (thread1 in this case) a predetermined number of times and after each "set" I need the thread with the getter method (thread2) to run and get the object. I have looked at many other examples, but I can't seem to work it out, so any help or explanation of why this isn't working would be appreciated.

This works sometimes, when thread1 runs first, but some other times thread2 runs first, so the synchronization isn't working.

Thanks.

import java.util.ArrayList;

public class ThreadTest{

    private ArrayList<Object> myList;

    public ThreadTest(){

        myList = new ArrayList<Object>();

        Thread thread1 = new Thread(){
            public void run(){
                for(int i = 0; i < 10; i++){
                    addToList("" + i);
                }
            }
        };

        Thread thread2 = new Thread(){
            public void run(){
                for(int i = 0; i < 10; i++){
                    System.out.print(myList.get(i) + " ");
                }
            }
        };

        thread1.start();
        thread2.start();
    }

    public synchronized void addToList(String a){
        myList.add(a);
        notify();
    }

    public synchronized ArrayList<Object> getList(){
        try{
            wait();
        }
        catch (InterruptedException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return myList;
    }

    public static void main(String[] args){
        new ThreadTest();
    }
}

Solution

  • Use a BlockingQueue to do your syncronization automagically, use an ExecutorService to deal with all the Threads

    public void doStuff() {
        final Object finishSupplying = new Object();
        final BlockingQueue<Object> myList = new LinkedBlockingQueue<Object>();
        final Runnable supplier = new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    myList.add(i);
                }
            }
        };
    
        final Runnable consumer = new Runnable() {
            public void run() {
                while (true) {
                    try {
                        final Object thing = myList.take();
                        if(thing == finishSupplying) break;
                        System.out.print(thing + " ");
                    } catch (InterruptedException ex) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        };
    
        final ExecutorService exectutorService = Executors.newFixedThreadPool(2);
        final Future<?> supplierHandle = exectutorService.submit(supplier);
        final Future<?> consumerHandle = exectutorService.submit(consumer);
        try {
            supplierHandle.get();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException ex) {
            //PROBLEMS, handle
        }
        myList.add(finishSupplying);
        try {
            consumerHandle.get();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException ex) {
            //PROBLEMS, handle
        }
    }
    

    Make sure you shutdown() the ExecutorService when you're done otherwise you're program will not exit.