简体   繁体   English

线程之间的同步ArrayList

[英]Synchronized ArrayList between Threads

I'm having a bit of difficulty understanding how to synchronize ArrayList's between threads in java. 我在理解如何在java中的线程之间同步ArrayList时遇到了一些困难。 Currently my code looks like: 目前我的代码如下:

Public class Runner {

    public static void main(String argv[]) {   
       Connect f = new Connect(irc.freenode.net, 6667);
       Thread ft = new Thread(f);
       ft.start();
       Connect q = new Connect(irc.quakenet.org, 6667);
       Thread qt = new Thread(q);
       qt.start();
       MessageParser mp = new MessageParser(f);
       MessageParser mp = new MessageParser(q);
       f.addMessage("Hello!");
       q.addMessage("World!");
    }

}

public class Connect {

    public List<String> l = new ArrayList<String>();

    public static void addMessage(String str) {
        l.add(str);
    }

}

The example is just to show what I'm doing, it isn't meant to make sense heh. 这个例子只是为了展示我正在做的事情,这并不意味着有意义。 Anyway I wanted to see if it was possible to have my ArrayList 'l' synched up between both threads. 无论如何,我想看看是否有可能让我的ArrayList'l'在两个线程之间同步。 So that running f.addMessage("Hello!"); 这样运行f.addMessage(“Hello!”); and q.addMessage("World!");, both messages will be readable by either class. 和q.addMessage(“World!”);,这两个消息都可以被任何一个类读取。 I know I could just easily make a seperate class that handles the ArrayList and pass it to both Connect classes but I wanted to see if there was an alternate way. 我知道我可以很容易地创建一个单独的类来处理ArrayList并将它传递给两个Connect类但我想看看是否有另一种方法。 I know about using a synchronizedList but I'm not very sure how that works and if it is applicable to my situation. 我知道使用synchronizedList,但我不太确定它是如何工作的,如果它适用于我的情况。

Thanks. 谢谢。

最好用Collections.synchronizedList包装List。

List<String> l = Collections.synchronizedList(new ArrayList<String>());

Yes, you can do that. 是的,你可以这么做。 The art is in making sure that you are very careful about synchronizing access to the list. 本文的目的是确保您在同步访问列表时非常小心。 SynchronizedList will often do the trick but it might not be exactly what you want. SynchronizedList通常会做到这一点,但它可能不是你想要的。 It will only synchronize individual method calls so it is not appropriate if you want to, say, atomically check for and remove the head of the list. 它只会同步单个方法调用,因此如果您想要自动检查并删除列表的头部,则它是不合适的。 In that case you need to manage synchronization yourself. 在这种情况下,您需要自己管理同步。

For example: 例如:

class Worker extends Thread {
    private List<String> l;
    public Worker(List<String> list) {
        this.l = list;
    }

    public void run() {
        try {
            while (true) {
                synchronized (l) {
                    if (!l.isEmpty()) {
                        String s = l.remove(0);
                        System.out.println(this + " processed " + s);
                    }
                    else {
                        l.wait(1000);
                    }
                }
            }
        }
        catch (InterruptedException e) {
        }
    }
}

class Main {
    public static void main(String[] args) {
        List<String> list = new LinkedList<String>();
        Worker w1 = new Worker(list);
        Worker w2 = new Worker(list);
        w1.start();
        w2.start();
        synchronized (list) {
            list.add("Hello");
            list.add("World");
        }
    }
}

Hopefully you get the idea. 希望你明白了。 Synchronize on operations that need to read or write to the list and make sure that all threads involved (including main) are careful about access. 同步需要读取或写入列表的操作,并确保所涉及的所有线程(包括main)都小心访问。

In the example above the "Hello" and "World" strings are added atomically: neither worker can proceed until both items have been added and the main thread exits the synchronized block. 在上面的示例中,“Hello”和“World”字符串以原子方式添加:在两个项目都已添加且主线程退出synchronized块之前,工作者都无法继续。 This may or may not be what you want: if you don't need this level of control the maybe synchronizedList will be sufficient. 这可能是你想要的也可能不是你想要的:如果你不需要这个级别的控制,那么可能是synchronizedList就足够了。

EDIT: I'm guessing that your Connect threads are pulling new items out of the list and sending them to the IRC channels. 编辑:我猜你的Connect线程正在从列表中提取新项目并将它们发送到IRC频道。 This means you almost certainly want to do your own synchronization and wait/notify logic, or you may want to take a look at the java.util.concurrent package. 这意味着您几乎肯定想要进行自己的同步和等待/通知逻辑,或者您可能想要查看java.util.concurrent包。 There are a bunch of useful classes in there that could suit your needs. 那里有许多有用的课程可以满足您的需求。 synchronizedList is only good for the most basic of synchronization tasks so isn't really useful a lot of the time. synchronizedList仅适用于最基本的同步任务,因此在很多时候并不是很有用。

Consider a ConcurrentLinkedQueue instead, perhaps. 或许考虑使用ConcurrentLinkedQueue

Depends on the operations, but it's my friend for "passing messages" in Java (which looks to be the usage from the provided code). 取决于操作,但它是我在Java中传递消息的朋友(它看起来是提供的代码中的用法)。 I also like CopyOnWriteArrayList :-) Anyway, use the provided java.util.concurrent package. 我也喜欢CopyOnWriteArrayList :-)无论如何,使用提供的java.util.concurrent包。

Edit: SO question about ConcurrentLinkedQueue with some ineresting information. 编辑: 关于ConcurrentLinkedQueue的问题,有一些不太有用的信息。

Let both connect-objects share a reference to a Vector . 让两个连接对象共享对Vector的引用。 It's basically a synchronized version of ArrayList . 它基本上是ArrayList的同步版本。

Something like this: 像这样的东西:

public class Runner {

    public static void main(String argv[]) {   

       List<String> l = new Vector<String>();

       Connect f = new Connect(irc.freenode.net, 6667, l);
       Thread ft = new Thread(f);
       ft.start();
       Connect q = new Connect(irc.quakenet.org, 6667, l);
       Thread qt = new Thread(q);
       qt.start();
       MessageParser mp = new MessageParser(f);
       MessageParser mp = new MessageParser(q);
       f.addMessage("Hello!");
       q.addMessage("World!");
    }

}

public class Connect {

    List<String> l;

    public class Connect(String host, int port, List<String> l) {
        this.l = l;
        // ...
    }

    public static void addMessage(String str) {
        l.add(str);
    }
}

From the API docs: 来自API文档:

As of the Java 2 platform v1.2, this class was retrofitted to implement the List interface, making it a member of the Java Collections Framework. 从Java 2平台v1.2开始,这个类被改进以实现List接口,使其成为Java Collections Framework的成员。 Unlike the new collection implementations, Vector is synchronized. 与新的集合实现不同,Vector是同步的。

Synchronized list is a good way to go. 同步列表是一个很好的方法。 It also makes it easy to use a different concrete list type later on down the road if you want to (eg LinkedList instead of an ArrayList). 如果您愿意,它还可以在以后随时轻松使用不同的具体列表类型(例如LinkedList而不是ArrayList)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM