Java中的线程隔离

发布于 2024-08-02 22:02:03 字数 304 浏览 4 评论 0原文

在 Java 中,有没有一种可靠的方法可以确保线程保持彼此隔离?我已经遇到一个半星期的问题了,由于静态变量和其他真正超出我控制范围的事情,实现各种第 3 方源代码的线程不断发生冲突。

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

我几乎就要为我想要的这个程序的每个实例启动一个新的流程,但我真的不想走这条路(这会消除很多实际的-我收集的时间数据,也会阻碍我杀死目标进程的能力)。

建议?谢谢!

Is there any sure-fire way to ensure threads remain isolated from one another, in Java? I've had an issue for a week and a half, where threads implementing various 3rd party source code keep colliding due to static variables and other such things that are really beyond my control.

I know a single system can run as many instances of the project I'm working on, as it wants. But when trying to incorporate everything into a threaded, single executable, there are always errors and exceptions.

I'm almost at the point of just launching a new process for each instance of this program that I want, but I'd really rather not go down this route (it would eliminate a lot of real-time data I gather, as well as hinder my ability to kill a targeted process).

Suggestions? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

落日海湾 2024-08-09 22:02:03

如果您要使用的库的作者未将其代码设计为线程安全的,那么除了防止两个线程同时调用它之外,您几乎无能为力。

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

根据偏好将是:

1)。为不安全代码设置一个单线程工作线程。尝试在多线程应用程序中完成尽可能多的工作,并尽可能少地投入到 Worker 中。

2)。如果工作程序是处理的主要部分,因此您确实需要并行执行将工作程序拉入多个单独的进程,请使用一些 IPC 通信来共享工作。这感觉 JMS 队列解决方案可能工作得很好。

3)。如果您无法承担 IPC 开销,请尝试找到库的线程安全替代方案,或者如果您有影响力与作者一起让他们修复代码。增加它们的并行性确实不应该那么困难。

If the authors of the library you want to use have not designed their code to be thread safe, then there's little you can easily do except to prevent two of your threads calling it at the same time.

You can pull some tricks with classloaders, but this tends to lead to a whole new world of complexity. To elaborate, it's possible to load the same class twice (or more times) into the same JVM, if you use different classloaders - hence you could effectively get independent copies of static variables. This use of separate classloaders is exploited by some Java EE Application Servers. That in turn leads to questions of which classloader and classpath gets used when the libraries themselves start to do some reflection and dynamic classloading. I would not recommend this approach unless your need is very great.

By preferences would be:

1). Have a single-threaded worker for the unsafe code. Try to do as much work as possible out in your mulit-threaded app, dropping into the Worker as little as you can.

2). If the worker is the major part of your processing and so you really need parallel execution pull the worker out into mulitple separate processes, use some IPC communication to share the work out. This feels like a JMS queueing solution might work nicely.

3). If you can't afford the IPC overhead try to find a thread-safe alternative to the libraries, or if you have influence with the authors get them to fix the code. It really should not be that hard to increase their parallelism.

吻风 2024-08-09 22:02:03

由于静态变量和其他真正超出我控制范围的事情,实现各种第 3 方源代码的线程不断发生冲突。

如果确实如此,那么我认为您必须走上拥有单独进程的道路。如果您调用的代码不是线程安全的,那么您所能做的就是确保该代码一次仅由一个进程调用。这基本上消除了在不同线程中运行它的优点。

也会阻碍我杀死目标进程的能力

我在这里不明白你的意思。只有使用进程才能安全地终止处理,如果您不能完全控制所有运行的代码,则不可能以安全的方式使用线程来执行此操作。

另请参阅此问题了解类似问题的讨论。

Threads implementing various 3rd party source code keep colliding due to static variables and other such things that are really beyond my control.

If that's really the case then I think you have to go down that road of having separate processes. If the code you call is not thread-safe then all you can do is to make sure that this code is only called by one process at a time. Which basically eliminates the advantages of running it in a different thread.

as well as hinder my ability to kill a targeted process

I don't see your point here. Only with processes you can safely kill the processing, it is not possible to do this in a safe way with threads if you don't have complete control over all the code that is run.

See also this question for a discussion of a similar problem.

何其悲哀 2024-08-09 22:02:03

批准的 JSR-121 涵盖了您的要求。

2006年 没有听说太多关于 JSR-121 实现的信息,但快速搜索让我找到了 http://weblogs.java.net/blog/gczaj/archive/j2se/index.html

Your requirement is covered by JSR-121, which was approved in 2006.

I didn't hear much about implementations of JSR-121, but a quick search led me to http://weblogs.java.net/blog/gczaj/archive/j2se/index.html .

沩ん囻菔务 2024-08-09 22:02:03

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

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

There is no way to do this, unfortunately. If threads access shared resources they should lock these resources as required, otherwise your program will definitely face corruption of the shared state.

Maybe you can wrap access to the shared resources in a way that allows you to synchronize access?

我为君王 2024-08-09 22:02:03

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

You could use a separate class loader for each thread, to load the third-party libraries you want to keep separate.

︶ ̄淡然 2024-08-09 22:02:03

我快要到了
为每个启动新流程
我想要的这个程序的实例,
但我真的不想继续下去
路线(这会消除很多
我收集的实时数据以及
阻碍我杀死目标的能力
过程。)

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

虽然不清楚“实时”的含义,但如果每个子进程都写入其标准输出,则可以编写控制程序来读取和整理写入的输出。

I'm almost at the point of just
launching a new Process for each
instance of this program that I want,
but I'd really rather not go down this
route (it would eliminate a lot of
real-time data I gather, as well as
hinder my ability to kill a targeted
process.)

By the sounds of it, the code you are trying to reuse is really not designed to be used in a multi-threaded application. In this case, launching a separate Process for each instance might actually be your best option. Rather than hindering your ability to kill each instance, it should actually make this easier to do; see Process.destroy().

While it is not clear what you mean by "real-time", if each child process writes to its standard output, you can code your control program to read and collate the output as it is written.

喵星人汪星人 2024-08-09 22:02:03

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

您可以通过执行器来做到这一点:

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

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

You can try putting the resources in a single executor, in such way that you will never have two of those processes running in parallel.

The way you can do it is by means of Executors:

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

  public void addTask(Runnable bar) {
    executor.submit(bar);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文