【问题标题】:Java Multithread with shared List具有共享列表的 Java 多线程
【发布时间】:2016-01-22 22:19:15
【问题描述】:

我需要一点关于 java 多线程的帮助。我有这门课:

public class EdgeServer{

    private static final int ServidorBordaID = 9;
    private static final String urlLogin = "http://localhost/exehdager-teste/index.php/ci_login/logar";
    private static final String insertSensorURI = "http://localhost/exehdager-teste/index.php/cadastros/ci_sensor/gravaSensor";
    private static final String insertGatewayURI = "http://localhost/exehdager-teste/index.php/cadastros/ci_gateway/gravaGateway";
    private static ArrayList<Gateway> gatewaysCadastrados = new ArrayList<>();

    public static void main(String[] args) {
        // Start a user thread that runs the UPnP stack
        Thread clientThread = new Thread(new Descoberta());
        clientThread.setDaemon(false);
        clientThread.start();

        Thread publicationThread = new Thread(new Publication());
        publicationThread.setDaemon(false);
        publicationThread.start();
    }
}

线程 Descoberta 将根据需要将新项目添加到 gatewaysCadastrados 列表中。并且发布线程将读取此列表并为列表中的每个对象执行一个操作。

我只需要知道如何共享这个变量并将其传递给线程。我需要构建一个信号量来执行此操作吗?

【问题讨论】:

标签: java multithreading


【解决方案1】:

这里是示例代码,您可以在其中在两个线程之间共享列表,并且您需要对信号量使用等待和通知。

public class Descoberta extends Thread {
private  final ArrayList<Gateway> a = new ArrayList<>();
public Descoberta( ArrayList<Gateway> a) {
        this.a = a;
    }

    @Override
    public void run() {
         synchronized (a) {
                while(true){ // your condition
                    a.wait();
                }
                a.notify();
         }
    }
}

public class Publication extends Thread {
private  final ArrayList<Gateway> b = new ArrayList<>();
public Publication(ArrayList<Gateway> b) {
        this.b = b;
    }

    @Override
    public void run() {
         synchronized (b) {
                while(true){ // your condition
                    b.wait();
                }
                b.notify();
         }
    }
}

public class EdgeServer {
    public static void main(String args[]) {
        private final ArrayList<Gateway> gatewaysCadastrados = new ArrayList<>();
        Thread clientThread = new Descoberta(gatewaysCadastrados);
        Thread publicationThread = new Publication(gatewaysCadastrados);
        clientThread.start();
        publicationThread.start();
    }
}

【讨论】:

  • 但是那些线程会共享相同的数据?我的意思是,如果线程 clientThread 在 gatewaysCadastrados 上插入一个项目,publicationThread 会看到它吗?而且我真的需要一个信号量,假设只有一个线程会修改列表?
  • @Hubertokf 看看例如“CopyOnWriteList”。
  • 对不起,CopyOnWriteArrayList
  • @Fildor 是的!我用它制作了一份清单。非常感谢!
【解决方案2】:

将共享对象作为构造函数参数传递给相关可运行对象的简单方法;例如

Thread clientThread = new Thread(new Descoberta(gateways));
...
Thread publicationThread = new Thread(new Publication(gateways));

显然,各个Runnable的构造函数需要保存参数,以便它们的run()方法可以找到它们。

还有其他多种方式:

  • 如果可运行对象是同一个外部类实例中的内部类,它们可以访问外部类中的共享对象。

  • 如果共享状态存储在static 变量中,则可运行对象可以通过静态 getter 等访问它们。 (注意:这很可能是糟糕的设计......)


正如@Fidor 指出的那样,如果两个或多个线程要共享一个公共(可变)数据结构,那么它们需要同步它们对数据结构的读写操作。如果您忽略了这一点,您的应用程序很可能会出现难以重现和难以追踪的隐蔽错误。

【讨论】:

  • @Hubertokf 如果您以这种方式共享资源,则需要考虑该资源的同步。 “并发”命名空间有一些数据结构已经为您执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
相关资源
最近更新 更多