我了解到调用Object的wait()方法将释放对象监视器(如果存在).
但我有一些关于notify()通过另一个线程调用此对象的问题:
如果另一个(第3个)线程同时拥有对象监视器,那么等待线程是否会被唤醒?
如果第三个线程调用wait()此对象,那么等待线程会被唤醒吗?
是否可以确定线程是否在等待通知特定对象(java 1.4/java 5)
如果wait()在finalize()方法中调用会发生什么?
我有一个WindowsForms应用程序,似乎泄漏内存,所以我使用Redgate的ANTS内存分析器来查看我怀疑的对象,并发现它们只由已经在Finalizer Queue上的对象持有.很棒,究竟什么是Finalizer Queue?你能指出我最好的定义吗?你能分享任何轶事建议吗?
此外,Finalizer Queue上的所有根GC对象都是名为"caller" 的System.Windows.Forms.Control + ThreadMethodEntry对象的实例.我看到它涉及多线程UI交互,但除此之外我不太了解.原谅我明显的懒惰并承认无知,但这些资源都埋藏在供应商的组件中.我正在和供应商讨论这些问题,但我需要一些指导才能让我加快对话速度.你能指点我最有用的ThreadMethodEntry定义吗?任何轶事建议?
另外,我是否应该关注终结器队列中的这些对象?
更新:这篇红门文章很有帮助.
我一直在思考为什么我们建议,我们应该不释放里面的finalize管理资源.如果您在http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx上看到代码示例,并搜索字符串"Dispose(bool disposing)在两个不同的场景中执行"并阅读评论,你会明白我的意思.
我能想到的唯一可能性是,它可能与无法预测何时调用终结器的事实有关.有谁知道正确的答案?
谢谢,误导
所以这是迄今为止的故事,我有这个工作者,它使用AppDomain来执行某些任务.该域名设置和拆卸都很昂贵.所以我为工作者创建一个WeakReference对象的每个线程缓存,如下所示:
class Worker
{
[ThreadStatic]
static Dictionary<string, WeakReference> _workers;
public static Worker Fetch( ... ) { you get the idea }
private AppDomain _domain;
public Worker(...)
{
_domain = AppDomain.Create( ... );
}
~Worker()
{
AppDomain.Unload(_domain);
}
// bla bla bla
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,当GC收集时,似乎总是在调用AppDomain.Unload时引发异常:
System.CannotUnloadAppDomainException: Error while unloading appdomain. (Exception from HRESULT: 0x80131015)"
Run Code Online (Sandbox Code Playgroud)
所以我觉得这很奇怪,我知道我在那个领域没有任何"跑步"......这笔交易是什么?我想出了一点挖掘和反复试验:
~Worker()
{
new Action<AppDomain>(AppDomain.Unload)
.BeginInvoke(_domain, null, null);
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
可能重复:
为什么要实现finalize()?
我看到一些带有以下代码的java文件:
public void finalize() {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
Connection的finalize方法最好的做法?Connection或需要关闭其他对象,如PreparedStatement?我有这样的测试代码:
public class A : CriticalFinalizerObject
{
~A()
{
File.WriteAllText("c:\\1.txt", "1z1z1");
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
throw new Exception();
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我尝试在不从CriticalFinalizerObject派生A的情况下运行它.在该程序结束后没有调用终结器.这令我感到惊讶,因为我认为这更具确定性,但没关系.然后我读到了关于CriticalFinalizerObject的内容,确保调用它们的终结器.我从它那里得到了A. 你猜怎么着.它仍然没有被执行.我在做什么/理解错误?
(请不要写关于垃圾收集器是非确定性的明显的东西,我知道.事实并非如此,因为程序结束了,我想我可以安全地清理一个很好的未处理的托管异常.)
我试图弄清楚如何在C++/CLI中正确清理我的对象之后.
我已经阅读或浏览了这两篇文章(一,二)并查看了标准并查看了其他一些问题,特别是这一个问题.
我有各种各样的信息:
但也有很多混乱,部分是由于这一事实造成的
我想要的答案是一个类的例子,它包含它可能包含的所有不同类型的数据(托管,非托管,托管但是一次性的,你能想到的其他任何东西)和正确编写的析构函数和终结器.
我有两个更具体的问题:
bool hasBeenCleanedUp成员处理多次被调用的可能性并使析构函数/终结器中的整个代码以此为条件,是否可以接受?我一直在研究内存泄漏并使用内存分析器工具来检查它们.因此,作为一种实践,我有以下代码泄漏活动,因为匿名内部类持有对活动的引用.这是代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleOne();
}
private void exampleOne() {
new Thread() {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}.start();
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里有上述泄漏的记忆分析仪图像(6次旋转):

很明显,有6个正在运行的线程持有对外部活动的隐式引用,从而防止它被垃圾回收.
现在,请考虑以下代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleTwo();
}
private void exampleTwo() {
new MyThread().start();
}
private static class MyThread extends Thread {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
} …Run Code Online (Sandbox Code Playgroud) IDisisposable模式实现起来很昂贵.在开始实际处理资源之前,我已经计算了17行代码.
Eric Lippert最近撰写了一篇博客文章,提出了一个有趣的观点:任何时候终结者都会运行,这是一个错误.我觉得这很有道理.如果始终遵循IDisposable模式,则应始终抑制Finalizer.它永远不会有机会跑.如果我们接受终结器运行是一个错误,那么有一个指导方针迫使开发人员从以下抽象类派生并禁止直接实现IDisposable接口.
public abstract class AbstractDisaposableBase: IDisposable
{
~AbstractDisaposableBase()
{
ReportObjectLeak();
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Dispose(bool disposing);
[Conditional("DEBUG")]
private void ReportObjectLeak()
{
//Debug.Assert(false, "leaked instance");
//throw new Exception("leaked instance");
}
}
Run Code Online (Sandbox Code Playgroud)
好处很明显:
class MyClass1 : DisablableBase
{
protected override void Dispose(bool disposing)
{
//dispose both managed and unmamaged resources as though disposing==true
}
}
Run Code Online (Sandbox Code Playgroud)
没有处置对象报告
始终遵循一次性模式
但是,这样的指南有什么问题吗?
一个可能的问题是所有一次性物体都将定义一个终结器.但由于终结器总是受到抑制,因此不应该有任何性能损失.
你的想法是什么?
我有很多实例,每个实例都有一个唯一的临时文件供其使用(将数据从内存保存到磁盘并稍后检索它们)。
我想确保最终所有这些文件都被删除。然而,我想留出空间来对它们的删除进行细粒度的控制。也就是说,如果需要的话,某些文件可以提前删除(例如,它们太大并且不再重要)。
实现这一目标的最佳/推荐方法是什么?
可能对此有想法
块try-finalize或with语句不是一个选项,因为我们有许多文件,它们的生命周期可能会相互重叠。而且,它几乎不承认更精细控制的选择。
从我读到的内容来看,__del__这也不是一个可行的选择,因为它甚至不能保证它最终会运行(尽管我并不完全清楚什么是“有风险”的情况)。此外(如果仍然如此),__del__运行时库可能不可用。
tempfile图书馆似乎很有前途。然而,文件在关闭后就消失了,这绝对是一个遗憾,因为我希望它们被关闭(当它们不执行任何操作时)以限制打开文件的数量。
该库承诺该文件“一旦关闭(包括对象被垃圾收集时的隐式关闭)就会被销毁”。
他们如何实现隐式关闭?例如,在 C# 中,我会使用(可靠的)终结器,但事实__del__并非如此。
atexit库似乎是最好的候选者,它可以作为可靠的终结器,而不是__del__实现安全的一次性模式。与对象终结器相比,唯一的问题是它真正在退出时运行,这相当不方便(如果对象有资格更早地被垃圾收集怎么办?)。
在理想情况下,似乎__del__和atexit库的组合可能表现最好。也就是说,清理既在 at__del__又在 中注册的方法进行atexit,而禁止重复清理。如果__del__被调用,注册的将被删除。
唯一(但也很关键)的问题是,__del__如果在 处注册了方法,则该方法不会运行atexit,因为对该对象的引用永远存在。
因此,欢迎任何建议、建议、有用的链接等。
finalizer ×10
c# ×4
.net ×2
java ×2
memory-leaks ×2
android ×1
appdomain ×1
architecture ×1
c++-cli ×1
clr ×1
del ×1
destructor ×1
disposable ×1
dispose ×1
locking ×1
notify ×1
python ×1
redgate ×1
wait ×1
winforms ×1