java:更新thread.start()前后的变量

ztyzrc3y  于 2021-07-05  发布在  Java
关注(0)|答案(1)|浏览(224)

我有两节课

classA {
    private ArrayList<String> list = new ArrayList();

    void addString(String s){
        list.add(s);
    }

    void start(){
        new ClassB(list).start();
    }
}

classB extends Thread{
    ArrayList<String> s;

    public ClassB(ArrayList<String> s) { this.s = s; }

    void run(){
        for (String s1 : s){
        // print s1
        }
    }
}

现在当我把代码写成

ClassA A = new ClassA();
A.addString("1");
A.addString("2");
A.addString("3");
A.start();

我希望classb中的run()打印列表中的所有元素。i、 e(1,2,3)。
这总是默认的还是我们需要应用多线程概念来实现它?
如果列表是非易失性的呢?新线程是否可以看到所有元素(1、2、3)
如果我在a.start()之后添加另一个元素(比如a.addstring(“4”),那么我应该怎么做才能让新线程打印所有4个元素呢?

gk7wooem

gk7wooem1#

如果在启动另一个线程(classb)之前添加所有元素,则是安全的。jls公司§17.4.4说:
启动线程的操作与它启动的线程中的第一个操作同步。
与中定义的同步§17.4.5.:
如果一个动作x与后面的动作y同步,那么我们还有hb(x,y)。
(hb(x,y)=x发生在y之前)
因此,这保证了在读取和打印元素之前添加元素。
但是,在当前代码中,如果在启动另一个线程之后从主线程添加元素,那么将没有线程安全保证,并且行为未定义。另一个线程可能会看到添加的元素,但也可能看不到它们,甚至可能会抛出异常,因为它看到了 ArrayList 处于不一致的状态。
如果我在a.start()之后添加另一个元素(比如a.addstring(“4”),那么我应该怎么做才能让新线程打印所有4个元素呢?
这很难用示例代码来回答,因为不清楚代码应该如何运行:
另一个线程(classb)是否应该无限期地等待新元素?然后一种解决方案可以是使用blockingqueue,或者使用某种信令,并且需要使用线程安全的集合(或者同步对arraylist的访问)。
如果另一个线程(classb)在添加新元素之前已经完成了旧元素的打印,是否允许它错过新元素?然后只需要使用线程安全的集合(或同步访问arraylist)。
...

相关问题