用例
我有一个基于gRPC Guice的服务应用程序,其中对于特定的调用,代码流如下所示:a-
其中,A=顶级服务操作/活动类;B=创建以C类为任务的ExecutorService线程池的类;X和Y是普通类。
我希望在这些类的B、C和Y类之间有一个共享对象
ContainerDoc
,但不希望传递给方法参数。因此,我决定使用InheritableThreadLocal。
但我想了解如何强制将父线程本地
ContainerDoc
共享给子线程,以便子线程在ContainerDoc
中执行的任何更新对父线程也是可见的?
重写childValue方法是否返回与父对象相同的包含对象以使其工作?(见下面的实施)。
- 如何确保线程安全
示例实现
class ContainerDoc implements ServiceDoc {
private final Map < KeyEnum, Object > containerMap;
public ContainerDoc() {
this.containerMap = new HashMap < KeyEnum, Object > ();
// Should it be ConcurrentHashmap to account for concurrent updates?
}
public < T > T getEntity(final KeyEnum keyEnum) {
return (T) containerMap.get(keyEnum);
}
public void putEntity(final KeyEnum keyEnum, final Object value) {
entities.put(keyEnum, value);
}
enum KeyEnum {
Key_A,
Key_B;
}
}
public enum MyThreadLocalInfo {
THREADLOCAL_ABC(ContainerDoc.class, new InheritableThreadLocal < ServiceDoc > () {
// Sets the initial value to an empty class instance.
@Override
protected ServiceContext initialValue() {
return new ContainerDoc();
}
// Just for reference. The below impl shows default
// behavior. This method is invoked when any new
// thread is created from a parent thread.
// This ensures every child thread will have same
// reference as parent.
@Override
protected ServiceContext childValue(final ServiceDoc parentValue) {
return parentValue;
// Returning same reference but I think this
// value gets copied over to each Child thread as
// separate object instead of reusing the same
// copy for thread-safety. So, how to ensure
// using the same reference as of parent thread?
}
}),
THREADLOCAL_XYZ(ABC.class, new InheritableThreadLocal < ServiceDoc > () {
....
....
});
private final Class << ? extends ServiceDoc > contextClazz;
private final InheritableThreadLocal < ServiceDoc > threadLocal;
MyThreadLocalInfo(final Class << ? extends ServiceDoc > contextClazz,
final InheritableThreadLocal < ServiceDoc > threadLocal) {
this.contextClazz = contextClazz;
this.threadLocal = threadLocal;
}
public ServiceDoc getDoc() {
return threadLocal.get();
}
public void setDoc(final ServiceDoc serviceDoc) {
Validate.isTrue(contextClazz.isAssignableFrom(serviceDoc.getClass()));
threadLocal.set(serviceDoc);
}
public void clearDoc() {
threadLocal.remove();
}
}
客户端代码(来自子线程类或常规类
MyThreadLocalInfo.THREADLOCAL_ABC.setDoc(new ContainerDoc());
MyThreadLocalInfo.THREADLOCAL_ABC.getDoc().put(Key_A, new Object());
MyThreadLocalInfo.THREADLOCAL_ABC.clearDoc();
返回相同的引用,但我认为这个值会作为单独的对象复制到每个子线程
运行时如何实例化这样一个“单独的对象”?这个理论是错误的。您的childValue()
实现与默认值完全相同。
当创建一个新线程时,将根据父线程为In遗产线程本地
分配一个值。ExecutorService
可以有任何实现,并且您没有指定如何创建线程,但是对于您的工作方法,父线程需要设置值,创建一个新线程,然后使用该新线程执行任务。换句话说,它只能工作于非池线程。
Threadlocal
是解决第三方代码中无法更改的设计缺陷的笨拙方法。即使它起作用了,这也是最后的手段——在这里,它不起作用。
根据需要将ServiceDoc
作为方法或构造函数参数传递给B、C和Y。
这可能意味着X也需要传递ServiceDoc
,但是,由于X-Y代码路径中没有Executor
,A可以在调用X之前有条件地初始化ThreadLocal
。这可能比将其作为参数传递更难看。
我注意到一些web框架(如Play Framework)允许您配置多个不同大小的线程池(线程池中的线程数)。假设我们在单核的单机中运行这个游戏。拥有多个线程池不会有很大的开销吗?
我创建了一个可运行的类a,它为我执行一些任务。我使用ExecutorService提交这个类,以便并行执行这些任务。 可运行类A调用另一个对象B,该对象发送一个AsyncFuture请求(future.get()one)。 我将可运行类A的单独对象提交给ExecutorService,但是,类B的对象由bean(单例)引用。这会导致线程执行出现问题吗? 我注意到类A的一些对象没有被任何线程执行。
问题内容: 我在程序开始时设置了numpy随机种子。在程序执行期间,我使用多次运行一个函数。该函数使用numpy随机函数绘制随机数。问题是获取当前环境的副本。因此,每个进程都独立运行,并且都以与父环境相同的随机种子开始。 所以我的问题是如何在父环境中与子进程环境共享numpy的随机状态?请注意,我想用于自己的工作,需要使用一个 单独的类 并在该类中单独进行操作。我尝试使用来共享随机状态,但是似乎事
在学习基本的线程管理时,我发现很难理解书中的这些行(粗体)。 一旦您启动了线程,您需要明确地决定是等待它完成(通过与它连接--参见第2.1.2)还是让它自己运行(通过分离它--参见第2.1.3)。如果在std::Thread对象被销毁之前没有做出决定,那么程序将被终止(std::Thread析构函数调用std::Terminate())。因此,即使存在异常,也必须确保线程正确连接或分离。有关处理此
问题内容: 我正在为我的ubuntu服务器(针对我的多客户端匿名聊天程序)实现一种简单的线程池机制,并且需要使我的工作线程进入睡眠状态,直到需要执行一项工作(以函数指针和参数的形式) 。 我当前的系统即将关闭。我(工人线程正在)问经理是否有工作可用,以及是否有5毫秒没有睡眠。如果存在,请将作业添加到工作队列中并运行该函数。糟糕的循环浪费。 什么我 喜欢 做的是做一个简单的事件性的系统。我正在考虑有
这是一个关于Java中多线程的初学者问题。 根据我的理解,当创建多个(用户)线程来运行程序或应用程序时,就没有父线程和子线程的概念。它们都是独立的用户线程。 因此,如果主线程完成执行,那么另一个线程(Thread2)仍将继续执行,因为在Thread2的执行线程完成之前,它不会被JVM杀死(https://docs.oracle.com/javase/6/docs/api/java/lang/Thr