0

我一直在寻找一种成功使用多线程和同步的方法。我试过使用 wait() 和 notify(),但我的线程仍然不同步。我有一个更大的项目,但简而言之,我需要它使用 setter 方法(在本例中为 thread1)运行线程预定次数,并且在每次“设置”之后,我需要使用 getter 方法(thread2)的线程运行并获取对象。我已经查看了许多其他示例,但我似乎无法解决,所以任何关于为什么这不起作用的帮助或解释将不胜感激。

这有时会起作用,当 thread1 首先运行时,但在其他时候 thread2 先运行,因此同步不起作用。

谢谢。

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();
    }
}
4

3 回答 3

2

使用 aBlockingQueue自动进行同步,使用 anExecutorService处理所有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
    }
}

确保您完成shutdown()ExecutorService,否则您的程序将不会退出。

于 2013-03-09T20:42:54.603 回答
1

当您通知时,您应该更新一个状态(正如您所拥有的),当您等待时必须在循环中检查该状态。这是必需的

  • 等待开始之前的通知触发器并且信号丢失
  • 等待可能会虚假地唤醒。

注意:您的消费线程不会等待,因为您没有调用任何等待的东西。

有很多方法可以解决这个问题,但恕我直言,最好的解决方案是使用旨在支持这种模式的 BlockingQueue。

于 2013-03-09T20:23:33.167 回答
0

您不应该使用 getter 和 setter 来访问整个列表,而只能从中推送和拉取元素。正如已经说过的,BlockingQueue是一个同步列表实现。

也就是说,如果你想自己实现这个,把getList替换为list上remove(0)的一个synchronized,它只返回ArrayList的第一个元素。

于 2013-03-09T20:42:18.420 回答