Java 为什么我要签入一个Runnable,它的线程不是null?
在我接管的一个项目中,我发现了这样的代码。我不确定if条件应该实现什么。如果Runnable正在运行,它会在检查为Java 为什么我要签入一个Runnable,它的线程不是null?,java,runnable,Java,Runnable,在我接管的一个项目中,我发现了这样的代码。我不确定if条件应该实现什么。如果Runnable正在运行,它会在检查为null的线程中执行此操作。所以情况总是这样,对吗 public class Outer { Thread m_thread = null; public Outer() { Runnable runner = new Runnable() { public void run()
null
的线程中执行此操作。所以情况总是这样,对吗
public class Outer
{
Thread m_thread = null;
public Outer()
{
Runnable runner = new Runnable()
{
public void run()
{
if ( m_thread != null )
do_stuff();
}
};
m_thread = new Thread(runner);
m_thread.start();
}
}
实际上还有另一种方法,它将
m_-thread
设置为null
,但是由于runnable中没有循环,这会有区别吗do_stuff()
不访问m_thread
,因为m_thread
未标记volatile
或由任何其他内存屏障操作保护,所以当运行Runnable
时,可能会观察到m_thread
为null
。如果do_stuff()
要求对m_thread
进行非空引用,则代码将失败
查看Shipilev的文章,了解Java中的安全发布习惯用法。简言之:
有几种简单的方法可以实现安全发布:
- 通过正确锁定的字段交换参考(JLS 17.4.5)
- 使用静态初始化器初始化存储(JLS 12.4)
- 通过volatile字段(JLS 17.4.5)交换引用,或者根据本规则,通过AtomicX类交换引用
- 将值初始化为最终字段(JLS 17.5)
由于
m_线程
未标记为volatile
或由任何其他内存屏障操作保护,因此当Runnable
运行时,它可能会观察到m_线程
为null
。如果do_stuff()
要求对m_thread
进行非空引用,则代码将失败
查看Shipilev的文章,了解Java中的安全发布习惯用法。简言之:
有几种简单的方法可以实现安全发布:
- 通过正确锁定的字段交换参考(JLS 17.4.5)
- 使用静态初始化器初始化存储(JLS 12.4)
- 通过volatile字段(JLS 17.4.5)交换引用,或者根据本规则,通过AtomicX类交换引用
- 将值初始化为最终字段(JLS 17.5)
简单地说:这没有任何意义。在Java中执行一行代码时,某个线程正在运行它 除非您开始实现自己的线程跟踪,否则您的代码正在运行的事实。。。告诉它某个线程正在运行它 这里显示的代码A)违反Java命名约定,B)违反Java中的“常识” 您可以看到,您仍然可以编写代码,首先初始化
m_thread
字段,然后直接从“主”线程调用runner.run()
。run方法将发现该字段不为null,并调用doStuff()
。如果有的话,您可以检查Thread.getCurrentThread()
是否返回比“主”线程更的内容
例如:
class Outer {
private Thread mainThread;
public Outer()
{
mainThread = Thread.getCurrentThread();
Runnable runner = new Runnable()
{
public void run()
{
if ( Thread.getCurrentThread() != mainThread )
do_stuff();
}
};
m_thread = new Thread(runner);
m_thread.start();
}
(我没有通过编译器运行上面的内容,这是一个“类似伪代码”的示例,不一定100%正确)简单地说:这没有任何意义。在Java中执行一行代码时,某个线程正在运行它 除非您开始实现自己的线程跟踪,否则您的代码正在运行的事实。。。告诉它某个线程正在运行它 这里显示的代码A)违反Java命名约定,B)违反Java中的“常识” 您可以看到,您仍然可以编写代码,首先初始化
m_thread
字段,然后直接从“主”线程调用runner.run()
。run方法将发现该字段不为null,并调用doStuff()
。如果有的话,您可以检查Thread.getCurrentThread()
是否返回比“主”线程更的内容
例如:
class Outer {
private Thread mainThread;
public Outer()
{
mainThread = Thread.getCurrentThread();
Runnable runner = new Runnable()
{
public void run()
{
if ( Thread.getCurrentThread() != mainThread )
do_stuff();
}
};
m_thread = new Thread(runner);
m_thread.start();
}
(我没有通过编译器运行上面的内容,这是一个“类似伪代码”的示例,不一定100%正确)你没有。20年前有一种时尚,我认为可能起源于一本杂志,即
run()
方法循环,而(Thread.currentThread()!=null)
。它在当时和现在都是毫无意义的,即使是在代码中稍微重新表达出来。你没有。20年前有一种时尚,我认为可能起源于一本杂志,即run()
方法循环,而(Thread.currentThread()!=null)
。它在当时毫无意义,现在也毫无意义,即使在代码中稍微重新表达。不管怎样,运行程序在新线程(运行程序)
中使用,也毫无意义,此线程
将永远不会为空
…是否有其他地方的代码将m_Thread
设置为空?这看起来像是简化了代码:可能有一些相关的细节被忽略了。创建线程充当了写/读屏障。如果您设置了一个值,则该值对于该线程在此之后启动的任何线程都是可见的。不管怎样,runner
在新线程(runner)
中使用都没有意义,此线程
将永远不会为空
…是否有其他地方的代码将m_Thread
设置为空?这看起来像是简化了代码:可能有一些相关的细节被忽略了。创建线程充当了写/读屏障。如果您设置了一个值,该值将对该线程在此之后启动的任何线程可见。创建线程是一个读/写内存屏障,因此代码不会失败。创建线程是一个读/写内存屏障,因此代码不会失败。