gpt4 book ai didi

java - 多线程初学者问题

转载 作者:行者123 更新时间:2023-11-29 03:42:50 25 4
gpt4 key购买 nike

如您所知,我是多线程的新手,有点卡在这里。对于我的程序,我需要一个线程(下例中的 PchangeThread),它可以在程序执行期间的任何时候从另一个线程打开和关闭。调用 pixelDetectorOn() 时,线程应在启动和恢复时挂起。

除了开始/停止标志外,这两个线程很可能不需要共享任何数据。为了以防万一,我还是包含了对主线程的引用。

然而,在下面的代码中,唯一输出的消息是“进入循环之前”,这表明线程由于某种原因永远不会从 wait() 中唤醒。我猜这是某种锁定问题,但我无法弄清楚到底出了什么问题。从主线程锁定 this.detector 给我同样的结果。我还想知道 wait()/notify() 范例是否真的是暂停和唤醒线程的方法。

public class PchangeThread extends Thread {
Automation _automation;
private volatile boolean threadInterrupted;

PchangeThread(Automation automation)
{
this._automation = automation;
this.threadInterrupted = true;
}

@Override
public void run()
{
while (true) {
synchronized (this) {
System.out.println("before entering loop");
while (threadInterrupted == true) {
try {
wait();
System.out.println("after wait");
} catch (InterruptedException ex) {
System.out.println("thread2: caught interrupt!");
}
}
}
process();
}
}

private void process()
{
System.out.println("thread is running!");

}

public boolean isThreadInterrupted()
{
return threadInterrupted;
}

public synchronized void resumeThread()
{
this.threadInterrupted = false;
notify();
}
}

resumeThread() 通过以下方式从主线程调用:

public synchronized void pixelDetectorOn(Context stateInformation) {        
this.detector.resumeThread();
}

detector 是对 PchangeThread 实例的引用。“检测器”线程在程序的主模块中按以下方式实例化:

detector=new PchangeThread(this);

最佳答案

如您所说,您需要保护对共享标志的访问。您声明了 threadInterrupted volatile,但仍在使用 syncronized。你只需要一个。我更喜欢只使用 syncronized,因为它使事情变得更简单。多线程已经够复杂了,保持简单,除非你知道你需要更复杂的控制。这意味着任何时候读取或写入 threadInterrupted 时,访问都应该同步。目前,您没有在 setThreadInterrupt()isThreadInterrupted() 中执行此操作。

其次,您希望在尽可能小的代码块上进行同步。在 run() 内部,您通过内部循环进行同步。实际上,您只需要在读取threadInterrupted 时进行同步。当 isThreadInterrupted() 的实现如上所述固定后,您可以直接使用它并从内部循环中删除同步块(synchronized block)。

您在内循环上同步的事实是导致您的代码永远不会打印“线程正在运行!”的错误。 PchangeThread 获取自身的锁并调用 wait() 挂起线程。但是,此时线程仍然持有锁。稍后,主线程调用 resumeThread() 以重新启动线程。但是,该方法无法开始执行,因为它必须先等待获取锁。但是,在通知 PchangeThread 之前,它永远不会获得锁。

您提供了两种设置threadInterrupted 的方法,但只有其中一种方法在值设置为false 时通知线程。您真的需要 setThreadInterrupt() 吗?我希望你不会。如果保留它,当参数为 false 时,它​​的行为应该与 resumeThread() 相同。

最后,最好锁定私有(private)对象而不是实例本身。您可以完全控制私有(private)锁对象。但是,任何引用您的线程实例的人也可以将其用作同步块(synchronized block)的锁,这可能会导致难以发现死锁。

您的代码已更改为使用我的编辑:

public class PchangeThread extends Thread {
private final Object _lock = new Object();
Automation _automation;
private final boolean _threadInterrupted;

PchangeThread(Automation automation)
{
_automation = automation;
_threadInterrupted = true;
}

@Override
public void run()
{
while (true) {
System.out.println("before entering loop");
while (isThreadInterrupted()) {
try {
wait();
System.out.println("after wait");
} catch (InterruptedException ex) {
System.out.println("thread2: caught interrupt!");
}
}
process();
}
}

private void process()
{
System.out.println("thread is running!");

}

public boolean isThreadInterrupted()
{
synchronized (_lock) {
return _threadInterrupted;
}
}

public void resumeThread()
{
synchronized (_lock) {
_threadInterrupted = false;
notify();
}
}
}

关于java - 多线程初学者问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12339704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com