Java中的线程隔离

时间:2009-08-17 14:11:22

标签: java multithreading process isolation

是否有任何确定的方法可以确保线程在Java中保持彼此隔离?我有一个半星期的问题,其中实现各种第三方源代码的线程由于静态变量和其他我无法控制的事情而保持冲突。

我知道单个系统可以按照自己的意愿运行我正在处理的项目的多个实例。但是当试图将所有内容合并到一个线程化的单个可执行文件中时,总会出现错误和异常。

我几乎正在为我想要的这个程序的每个实例启动一个新的进程,但我真的不想沿着这条路走下去(它会消除很多我收集的实时数据,以及阻碍我杀死目标进程的能力。)

连连呢?谢谢!

7 个答案:

答案 0 :(得分:11)

如果你想要使用的库的作者没有设计他们的代码是线程安全的,那么除了防止你的两个线程同时调用它之外你几乎没什么可以做的。

你可以用类加载器来汲取一些技巧,但这往往会带来一个全新的复杂世界。详细说明,如果使用不同的类加载器,可以将同一个类加载到同一个JVM中两次(或更多次) - 因此您可以有效地获得静态变量的独立副本。某些Java EE应用程序服务器利用了单独的类加载器。这反过来会导致在库本身开始进行反射和动态类加载时使用哪个类加载器和类路径的问题。除非你的需求很大,否则我不会推荐这种方法。

根据偏好:

1)。有一个单线程工作者来处理不安全的代码。尝试在你的多线程应用程序中尽可能多地完成工作,尽可能少地投入到工作者中。

2)。如果工作人员是您处理的主要部分,那么您确实需要并行执行将工作人员分成多个单独的进程,使用一些IPC通信来共享工作。这感觉就像JMS排队解决方案可能会很好地工作。

3)。如果你负担不起IPC开销试图找到一个线程安全的替代库,或者如果你对作者有影响力,让他们修复代码。增加并行性确实不应该那么难。

答案 1 :(得分:4)

  

实现各种第三方源代码的线程由于静态变量和其他我无法控制的事情而不断发生冲突。

如果情况确实如此,那么我认为你必须沿着这条道路走下去。如果您调用的代码不是线程安全的,那么您所能做的就是确保此代码一次只能被一个进程调用。这基本上消除了在不同线程中运行它的优点。

  

以及妨碍我杀死目标进程的能力

我不明白你的观点。只有使用进程才能安全地终止处理,如果您无法完全控制所有运行的代码,则无法以安全的方式使用线程执行此操作。

有关类似问题的讨论,另请参阅this question

答案 2 :(得分:2)

您的要求由JSR-121涵盖,并于2006年获得批准。

我没有太多关于JSR-121的实现,但快速搜索引导我http://weblogs.java.net/blog/gczaj/archive/j2se/index.html

答案 3 :(得分:0)

不幸的是,没有办法做到这一点。如果线程访问共享资源,则应根据需要锁定这些资源,否则您的程序肯定会面临共享状态的损坏。

也许您可以以允许您同步访问的方式包装对共享资源的访问权限?

答案 4 :(得分:0)

  

我差点就到了   为每个人启动一个新流程   我想要的这个程序的实例,   但我真的不愿意这样做   路线(它会消除很多   我收集的实时数据,以及   阻碍我杀死目标的能力   过程。)

听起来,您尝试重用的代码实际上并不是设计用于多线程应用程序。在这种情况下,为每个实例启动单独的Process实际上可能是您的最佳选择。它实际上应该更容易做到,而不是阻碍你杀死每个实例的能力;见Process.destroy()

虽然不清楚“实时”是什么意思,但如果每个子进程都写入其标准输出,您可以编写控制程序来编写输出,并在输出时对其进行整理。

答案 5 :(得分:0)

您可以为每个线程使用单独的类加载器,以加载要保持独立的第三方库。

答案 6 :(得分:0)

您可以尝试将资源放在单个执行程序中,这样您就不会有两个并行运行的进程。

你可以通过执行者的方式来做到这一点:

class Foo {
  private ExecutorService executor = Executors.newSingleThreadExecutor();

  public void addTask(Runnable bar) {
    executor.submit(bar);
  }
}