Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程之间的同步ArrayList_Java_Multithreading_Arraylist - Fatal编程技术网

Java 线程之间的同步ArrayList

Java 线程之间的同步ArrayList,java,multithreading,arraylist,Java,Multithreading,Arraylist,我在理解如何在java中的线程之间同步ArrayList时有点困难。当前我的代码如下所示: 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 C

我在理解如何在java中的线程之间同步ArrayList时有点困难。当前我的代码如下所示:

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

}
公共类运行程序{
公共静态void main(字符串argv[]){
Connect f=新连接(irc.freenode.net,6667);
螺纹ft=新螺纹(f);
ft.start();
Connect q=新连接(irc.quakenet.org,6667);
螺纹qt=新螺纹(q);
qt.start();
MessageParser mp=新的MessageParser(f);
MessageParser mp=新的MessageParser(q);
f、 添加消息(“你好!”);
q、 添加消息(“世界!”);
}
}
公共类连接{
public List l=new ArrayList();
公共静态void addMessage(字符串str){
l、 添加(str);
}
}
这个例子只是为了说明我在做什么,它并不意味着有意义。无论如何,我想看看是否有可能让我的ArrayList“l”在两个线程之间同步。所以运行f.addMessage(“你好!”);和q.addMessage(“世界!”);,这两条消息都可以被任何一个类读取。我知道我可以很容易地创建一个单独的类来处理ArrayList并将其传递给两个Connect类,但我想看看是否有其他方法。我知道使用a,但我不太确定它是如何工作的,以及它是否适用于我的情况


谢谢。

让两个连接对象共享对
向量的引用。它基本上是一个同步版本的
ArrayList

大概是这样的:

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);
    }
}
公共类运行程序{
公共静态void main(字符串argv[]){
列表l=新向量();
Connect f=新连接(irc.freenode.net,6667,l);
螺纹ft=新螺纹(f);
ft.start();
Connect q=新连接(irc.quakenet.org,6667,l);
螺纹qt=新螺纹(q);
qt.start();
MessageParser mp=新的MessageParser(f);
MessageParser mp=新的MessageParser(q);
f、 添加消息(“你好!”);
q、 添加消息(“世界!”);
}
}
公共类连接{
清单l;
公共类连接(字符串主机、int端口、列表l){
这个。l=l;
// ...
}
公共静态void addMessage(字符串str){
l、 添加(str);
}
}
从API文档中:

从Java2平台v1.2开始,这个类被改装以实现List接口,使其成为Java集合框架的成员。与新的集合实现不同,Vector是同步的


最好使用Collections.synchronizedList包装列表

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

同步列表是一个很好的方法。如果您愿意,也可以在以后使用不同的具体列表类型(例如LinkedList而不是ArrayList)。

是的,您可以这样做。艺术在于确保您在同步访问列表时非常小心
SynchronizedList
通常会起作用,但它可能不是您想要的。它只会同步单个方法调用,因此,如果您想(比如)以原子方式检查并删除列表的开头,那么它是不合适的。在这种情况下,您需要自己管理同步

例如:

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");
        }
    }
}
类工作线程扩展{
私人名单l;
公职人员(名单){
这个。l=列表;
}
公开募捐{
试一试{
while(true){
同步(l){
如果(!l.isEmpty()){
字符串s=l.remove(0);
System.out.println(此+“已处理”+s);
}
否则{
l、 等待(1000);
}
}
}
}
捕捉(中断异常e){
}
}
}
班长{
公共静态void main(字符串[]args){
列表=新建LinkedList();
工人w1=新工人(列表);
工人w2=新工人(列表);
w1.start();
w2.start();
已同步(列表){
添加(“你好”);
列表。添加(“世界”);
}
}
}
希望你能明白。对需要读取或写入列表的操作进行同步,并确保所有涉及的线程(包括main)都小心访问

在上面的示例中,“Hello”和“World”字符串是以原子方式添加的:在添加了这两个项并且主线程退出synchronized块之前,两个工作线程都不能继续。这可能是您想要的,也可能不是您想要的:如果您不需要这种级别的控制,那么可能
synchronizedList
就足够了

编辑:我猜您的
Connect
线程正在从列表中提取新项目并将它们发送到IRC频道。这意味着您几乎肯定要自己进行同步和等待/通知逻辑,或者您可能想看看java.util.concurrent包。那里有很多有用的类可以满足您的需要
synchronizedList
只适用于最基本的同步任务,因此在很多情况下并不真正有用。

或许可以考虑使用一个

这取决于操作,但它是我在Java中“传递消息”的朋友(这看起来是所提供代码的用法)。我也喜欢CopyOnWriteArrayList:-)无论如何,使用提供的包


编辑:带有一些惰性信息。

当然,您可以使用同步列表,只需根据需要使用
syncrhonized(xxx){…}
包装多个操作即可。这避免了显式地同步添加。这是一个选项,但我个人不会这么做。显式同步块使调试同步问题变得更容易,如果需要更容易的调试,那就是同步问题。为什么人们如此痴迷于向量?为什么人们如此痴迷于速度?