【问题标题】:Static Class with attributes and synchronized methods具有属性和同步方法的静态类
【发布时间】:2014-06-06 13:03:18
【问题描述】:

我知道 StackOverFlow 上有很多几乎相同的答案,但它们不符合我的需求。

给出以下代码示例:

(内部类)

static class OutgoingFileTransfer implements Runnable {

File sendThisFile;

outgoingFileTransfer(File sendThis) {
    this.sendThisFile = sendThis;
}

@Override
public synchronized void run() {
    //Send the file...  
}

}

我知道,同步方法将锁定整个类,但前提是调用了 run() 方法。如果我执行以下操作:

Thread a = new Thread(new OutgoingFileTransfer(new File("c:/.../file1"))).start();
Thread b = new Thread(new OutgoingFileTransfer(new File("c:/.../file2"))).start();

难道线程 a 初始化 file1 并在进入同步方法之前,然后线程 b 中断,设置 file2 并加入 run() 方法?这意味着永远不会发送 file1。对吧?

有没有办法防止这种情况发生?

我知道便宜的方法:让所有东西都不是静态的,然后添加一个boolean iAmCurrentlySendingAFilePleaseWaitInTheQueueTillTheOtherFileTransferFinished,这样所有东西都可以按顺序进行。但我认为会有更好的方法来做到这一点。谢谢你的帮助。 :)

【问题讨论】:

  • 我认为布尔值可能更具描述性,iAmCurrentlySendingAFilePleaseWaitInTheQueueTillTheOtherFileTransferFinishedBecauseIfYouDontThenWeWillRunIntoConcurrencyIssuesAndThoseJustArentFun
  • @Rogue:对不起,名字太长了。 :P
  • @Andres:如果类本身是静态的,那么方法也必须是静态的,还是我是假的?但无论如何,这是我的错。更改“静态”->“同步”
  • 在我看来,如果你同步 Runnable#run() 那么你无论如何都会渲染整个事情。
  • 如果类中没有其他同步方法,则使 run 方法同步是没有意义的。如果这是完整的定义,synchronized 修饰符就没有用了。此外,由于每个 OutgoingFileTransfer 对象都将由单个线程使用,因此不需要同步(除非这只是代码的一部分)。

标签: java multithreading synchronize


【解决方案1】:
Thread a = new Thread(new OutgoingFileTransfer(new File("c:/.../file1"))).start();
Thread b = new Thread(new OutgoingFileTransfer(new File("c:/.../file2"))).start();

使用两个不同的OutgoingFileTransfer 对象创建两个不同的线程。每个都有自己的sendThisFile 版本,并将对其进行操作。当多个线程同时作用于同一个对象时,同步和锁定就会发挥作用。在您的情况下,没有竞争条件的危险,两个线程是独立的并且并行运行。

编辑:
Java 中的静态类:
Java 只允许静态内部类,不允许静态顶级类。静态类不会使其中的所有内容都是静态的。 来自 Java 教程:

实际上,静态嵌套类在行为上是顶级类 已经嵌套在另一个顶级的包装类中 方便。

因此,静态类可以像任何其他类一样被实例化,可以在任何其他类中包含静态和非静态成员,并且静态和非静态成员的行为与任何其他类一样。

因此,在您的情况下,该类的 teo 独立实例有两个 sendThisFile 独立属性。在这种情况下,行为与 OutgoingFileTransfer 是顶级(因此非静态)类相同。

【讨论】:

  • 我知道对于普通对象,但是OutgoingFileTransfer,在这种情况下,是一个静态类吗?它不会阻止构建一个独特的对象吗?实际上我有点困惑,因为我什至不知道您可以创建这样的类的实例。
  • Java 只允许静态内部类,不允许静态顶级类。静态类不会使其中的所有内容都是静态的。来自The Java tutorials:实际上,静态嵌套类在行为上是一个顶级类,为了方便打包,它已经嵌套在另一个顶级类中。所以静态类可以像任何其他类一样被实例化,可以在任何其他类中包含静态和非静态成员,并且静态和非静态成员的行为与任何其他类一样。
【解决方案2】:

我认为这里的症结在于对嵌套类的 static 限定符的误解。

您只能将那些嵌套在其他类中的类声明为static,意思是

class A {
    static class B {
    }
}

外部类永远不能是静态的(在这个例子中,A)。 static 对于类意味着,嵌套类不需要围绕它的外部类的实例。这意味着如果B 是静态的,你可以这样做

A.B b = new A.B();

如果不是,你必须这样做:

A a = new A();
A.B b = new a.B();

这与static 的成员和方法的概念完全相反。

【讨论】:

  • 非常感谢。 :) 我想我必须采用我的布尔想法。
猜你喜欢
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-27
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
相关资源
最近更新 更多