Java同步静态列表?

时间:2011-01-16 06:04:39

标签: java multithreading static synchronization thread-safety

在Java类中,我有一个静态列表,所以这个列表在这个类的所有对象之间共享。这个类中的业务逻辑将定期运行,这是由一些方法调用而不传递实例参数。现在我想要根据列表调用此run方法(我将基于JMS将一些vales添加到此列表中),此列表有时可能会清空,并且在完成运行后,我正在清空此列表。现在我的问题是,我是否需要是否同步此列表?

另请告诉我是否还有其他方法可以将一个对象实例(Thread1)中的值传递给除静态变量(静态列表)之外的其他对象实例(Thread2)?

THX

5 个答案:

答案 0 :(得分:1)

如果列表是可变的并且由不同的线程访问(听起来像是这样),那么是的,你需要进行同步。 (如果它是不可变的,那么另一种选择是使其最终的静态引用。)

我建议先看看BlockingQueue类,这些类旨在允许一个线程(或实际上是多个线程)将项添加到“列表”,然后让另一个线程将项目拉出来处理它们。

答案 1 :(得分:1)

如果有可能从不同的线程访问和/或更新,那么您需要同步这些操作。

或者换句话说,只有 的情况可以省去列表中的同步操作:

  • 只有一个线程可以访问/更新列表,或
  • 列表被创建,初始化,包装在一个不可变的列表包装器中,并由一个线程安全地发布......然后永远不会更新。

  

另请告诉我是否有其他方法可以将一个对象实例(Thread1)中的值传递给除静态变量(静态列表)之外的其他对象实例(Thread2)?

有很多方法。例如:

  • 你可以安排thread2的runnable有一个公共setter,thread1的runnable可以用来将值传递给thread2。这需要一些额外的同步。

  • 您可以安排使用共享对象或可以用来来回传递spate的对象来实例化thread1和thread2。如果对象是通用(同步)队列或管道或其他,则线程不需要进行任何显式同步。

答案 2 :(得分:1)

您将需要同步对此列表的所有读取和写入,或者使用多线程功能列表(如CopyOnWriteArrayList,如果您使用的是更复杂的东西,甚至使用ConcurrentMap)。

否则,您需要具有良好的并发控制,以便不同的线程不会相互覆盖,并且其他线程也可以看到所做的更改。

重新编辑: 在线程之间传递数据的最佳方式是让它们共享数据结构。静态变量是一种方式,但它不是唯一的分享方式。您可以通过在两个线程中传递的公共对象进行共享(例如,在构造函数中)。通常,这称为队列,其中一个线程写入,而其他线程消耗。在java中,有一些阻塞队列可以使这更容易 - 请参阅此包中的许多不同的类http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/package-summary.html

答案 3 :(得分:1)

  
    

另请告诉我是否有其他方法可以将一个对象实例(Thread1)中的值传递给除静态变量(静态列表)之外的其他对象实例(Thread2)?

  

对象实例(Thread1)到其他对象实例(Thread2) - >需要静态变量,因为对象实例不同。 但是,如您所知,如果Thread1和Thread2在相同的对象上运行,则类的实例变量将在线程之间共享。所以不需要让它们变得静止。

答案 4 :(得分:0)

  
    

另请告诉我是否有其他方法可以将一个对象实例(Thread1)中的值传递给除静态变量(静态列表)之外的其他对象实例(Thread2)?

  

这里有两种不同的方法可以避免在这里使用静态变量。可能会有更多。

方法#1

class A implements Runnable {
  final Object x;
  public A (Object _x) {
    x = _x;
  }
  ...
}

// elsewhere .. hopefully from a NON-STATIC context
// where theObjectToShare is available
A th1 = new Thread(new A(theObjectToShare));
...

方法#2A / B:

object parentMemberVariable = ...;

function runStuff () {
  object _localFinal = parentMemberVariable;
  A th1 = new Thread(new Runnable {
    public void Run () {
      // NON-STATIC inner classes (including anonymous) can access
      // parents member variables. this is because there are created
      // "in the context of" the parent class.
      // This could also be done for the normal inner Runnables.
      foo(parentMemberVariable);
      // anonymous classes can also access final variables
      // in scope at declaration
      foo(_localFinal);
   }
});

快乐的编码。