【问题标题】:java access an object in different threadsjava在不同的线程中访问一个对象
【发布时间】:2012-01-24 05:45:06
【问题描述】:

我搜索了很多,但找不到特定的解决方案。在stackoverflow上也有一些关于此的问题,但我无法找到令人满意的答案,所以我再次询问。

我在 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
    }
}

现在我想同时进行这两个操作。为此,我创建了两个线程类,一个在运行中执行 addString() 逻辑,另一个执行 deleteString() 逻辑。我在每个线程的构造函数中传递 mylist,但是在对 mylist 执行添加和删除后如何返回对象?

之前我在想“如果我在线程的构造函数中传递 mylist,它会将 mylist 的地址传递给线程,并且线程对其执行操作,更改引用 mylist 对象”但它不是那样的,因为更改不反映到 mylist 对象。有人可以详细说明吗?

实现这一目标的最佳方法是什么?

要求就像如果一个线程最后插入一个元素,另一个线程应该能够同时删除另一个索引处的某个元素,比如第二个。

编辑

我已经这样做了:thanx to 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();
    }
}

还有其他方法吗?

【问题讨论】:

  • 您能展示一下您是如何制作线程的以及您是如何尝试插入和删除值的吗?
  • 您的问题非常令人困惑。您描述了myclass 类,但在您的问题中没有提到它。 mylist 只是一个包含addremove 的列表,你需要myclass 做什么?查看用于创建线程的代码和使用adddelete 的代码更为重要。
  • @AlexGitelman 请查看编辑
  • 在您的编辑中,我认为您可以使 addString() 和 deleteString() 同步方法,同时仍然为 mylist 使用普通的 ArrayList。如果我错了,请纠正我。

标签: java multithreading concurrency synchronization


【解决方案1】:

使用 同步列表 ,这将是线程安全的

使用Collection.synchronizedList(yourPlainList)

【讨论】:

  • 你能看到编辑并说我如何使用 Collection.synchronizedList(yourPlainList) 来实现它吗?
  • 我认为他要求对数据进行并发操作,这对于数组列表是不可行的,因为它们由普通数组支持。他想要一个 CopyOnWriteArrayList
  • 您的共享列表只需同步即可
  • @JigarJoshi 私有列表 mylist = Collections.synchronizedList(new ArrayList());完成。
  • @rahul 不会编译,synchronized 不是修饰符
【解决方案2】:

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

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 关键字。

【讨论】:

  • 对于并发操作,我使用了私有 List mylist = Collections.synchronizedList(new ArrayList());正如 jigar 所指定的那样。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 1970-01-01
  • 2014-07-13
相关资源
最近更新 更多