Java:在不同的线程中访问一个对象

qnakjoqk  于 2023-05-27  发布在  Java
关注(0)|答案(2)|浏览(151)

我找了很多,但找不到特别的解决办法。在Stack Overflow上也有一些关于这个的问题,但是我找不到满意的答案,所以我又问了一遍。
我在Java中有一个类。我知道如何在java中使用线程。

// Please do not consider syntax if there is printing mistake, as I am typing code just for showing the concept in my mind
    public class myclass{
    private List<String> mylist=new ArrayList<String>();

    public addString(String str) {
        // code to add string in list
    }

    public deleteString(String str) { // or passing an index to delete
        // code to delete string in list
    }
}

现在我想同时做这两个操作。为此,我创建了两个线程类,一个在run中执行addString()逻辑,另一个执行deleteString()逻辑。
我在每个线程的构造函数中传递mylist,但是在对mylist执行添加和删除操作后,如何返回对象?
之前我在想“如果我在线程的构造函数中传递mylist,它会将mylist的地址传递给线程,然后线程对它执行引用mylist对象的操作”。但它不是这样的,因为更改不会反映到mylist对象。有谁能详细说明一下吗?
实现这一目标的最佳途径是什么?
这个要求就像是,如果一个线程正在插入一个元素,那么另一个线程应该能够同时删除其他索引(比如说第二个索引)处的某个元素。

编辑

我是这样做的:谢谢Enno Shioji

public class myClass {
    
    private List<String> mylist = Collections.synchronizedList(new ArrayList<String>());
    public myClass() {
        mylist.add("abc");
        mylist.add("def");
        mylist.add("ghi");
        mylist.add("jkl");
    }
    public void addString(String str) {
        mylist.add(str);
    }

    public void displayValues() {
        for (int i = 0; i < mylist.size(); i++) {
            System.out.println("value is " + mylist.get(i) + "at " + i);
        }
    }

    public void deleteString(int i) {
        mylist.remove(i);
    }
}

class addThread {

    public static void main(String a[]) {
        final myClass mine = new myClass();
        Thread t1 = new Thread() {
            
            @Override
            public void run() {
                mine.displayValues();
                mine.addString("aaa");
                mine.displayValues();
            }
        };
        Thread t2 = new Thread() {
            
            public void run() {
                mine.displayValues();
                mine.deleteString(1);
                mine.displayValues();
            }
        };
        t1.start();
        t2.start();
    }
}

有没有其他办法呢?

pgpifvop

pgpifvop1#

使用同步列表,线程安全
使用Collection.synchronizedList(yourPlainList)

ccrfmcuu

ccrfmcuu2#

线程和对象示例是不同的概念。如果要在线程之间共享数据,则需要从两个线程访问单个对象示例。在这种情况下,你应该做这样的事情。

public class MyClass{
    private final List<String> mylist = new ArrayList<String>();

    public synchronized void addString(String str){
        //code to add string in list
    }

    public synchronized void deleteString(String str){
        //or passing an index to delete
        //code to delete string in list
    }
}

然后

final MyClass mine = new MyClass();
Thread t1 = new Thread(){
    public void run(){
        mine.addString("aaa");
    }
}();

Thread t2 = new Thread(){
    public void run(){
        mine.deleteString("bbb");
    }
}();

t1.start();
t2.start();

请注意您是如何从两个线程引用同一个对象示例(mine)的。另外请注意,我添加了synchronized关键字以使MyClass成为线程安全的。这迫使所有操作顺序地而不是真正地“同时”完成。如果你想在集合上进行真正的并发操作,你需要使用并发数据结构,比如Skip List,并去掉synchronized关键字。

相关问题