Java 1类中的同步线程

Java 1类中的同步线程,java,multithreading,wait,synchronized,notify,Java,Multithreading,Wait,Synchronized,Notify,我一直在寻找一种成功使用多线程和同步的方法。我已经尝试使用wait()和notify(),但我的线程仍然不同步。 我有一个更大的项目,但简而言之,我需要它使用setter方法(在本例中为thread1)运行线程预定次数,在每次“设置”之后,我需要使用getter方法(thread2)运行线程并获取对象。 我已经看过很多其他的例子,但我似乎不能解决它,所以任何帮助或解释为什么这不起作用都将不胜感激 有时,当thread1首先运行时,这是可行的,但有时thread2首先运行,因此同步不起作用 谢谢

我一直在寻找一种成功使用多线程和同步的方法。我已经尝试使用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();
    }
}
import java.util.ArrayList;
公共类线程测试{
私人ArrayList myList;
公共线程测试(){
myList=新的ArrayList();
线程thread1=新线程(){
公开募捐{
对于(int i=0;i<10;i++){
地址列表(“+i”);
}
}
};
线程thread2=新线程(){
公开募捐{
对于(int i=0;i<10;i++){
System.out.print(myList.get(i)+“”);
}
}
};
thread1.start();
thread2.start();
}
公共同步的void addToList(字符串a){
添加(a);
通知();
}
公共同步ArrayList getList(){
试一试{
等待();
}
捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
返回myList;
}
公共静态void main(字符串[]args){
新螺纹试验();
}
}

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

  • 等待开始前的notify触发器,信号丢失
  • 等待可能是虚假的
注意:您的消费线程不会等待,因为您没有调用任何等待的东西


有很多方法可以解决这个问题,但最好的解决方案是使用一个BlockingQueue,它是为支持这个模式而设计的。

当你发出通知时,你应该更新一个状态(正如你所做的那样),当你等待时,必须在循环中检查这个状态。这是必要的,因为

  • 等待开始前的notify触发器,信号丢失
  • 等待可能是虚假的
注意:您的消费线程不会等待,因为您没有调用任何等待的东西


有很多方法可以解决这个问题,但最好的解决方案是使用BlockingQueue,它是为支持这个模式而设计的。

您不应该使用getter和setter来访问整个列表,而应该只从列表中推拉元素。如前所述,
BlockingQueue
是一个同步列表实现


换句话说,如果您想自己实现这一点,请在列表上用一个同步的
remove(0)
替换getList,它只返回ArrayList的第一个元素。

您不应该使用getter和setter访问整个列表,而应该只从列表中推拉元素。如前所述,
BlockingQueue
是一个同步列表实现


换句话说,如果您想自己实现这一点,请在列表上用一个synchronized
remove(0)
替换getList,它只返回ArrayList的第一个元素。

使用
BlockingQueue
自动进行同步,使用
执行器服务
处理所有
线程

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
    }
}
public void doStuff(){
最终对象FinishSuppling=新对象();
final BlockingQueue myList=新建LinkedBlockingQueue();
最终可运行供应商=新可运行供应商(){
公开募捐{
对于(int i=0;i<10;i++){
添加(i);
}
}
};
最终可运行消费者=新可运行(){
公开募捐{
while(true){
试一试{
final Object thing=myList.take();
如果(事物==完成)中断;
系统输出打印(thing+“”);
}捕获(中断异常例外){
Thread.currentThread().interrupt();
}
}
}
};
final ExecutorService ExecutorService=Executors.newFixedThreadPool(2);
最终未来供应商句柄=ExecutorService.submit(供应商);
最终未来消费者handle=executorservice.submit(消费者);
试一试{
supplierHandle.get();
}捕获(中断异常例外){
Thread.currentThread().interrupt();
}捕获(ExecutionException ex){
//问题,处理
}
myList.add(完成供应);
试一试{
consumerHandle.get();
}捕获(中断异常例外){
Thread.currentThread().interrupt();
}捕获(ExecutionException ex){
//问题,处理
}
}

确保
shutdown()
当您完成此操作时,执行器服务将不会退出。

使用
阻塞队列来自动执行同步,使用
执行器服务来处理所有
线程

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
    }
}
public void doStuff(){
最终对象FinishSuppling=新对象();
final BlockingQueue myList=新建LinkedBlockingQueue();
最终可运行供应商=新可运行供应商(){
公开募捐{
对于(int i=0;i<10;i++){
添加(i);
}
}
};
最终可运行消费者=新可运行(){
公开募捐{
while(true){
试一试{
final Object thing=myList.take();
如果(事物==完成)中断;
Sy