当前位置: 首页 > 面试题库 >

为什么不按主要顺序进行呼叫?

司空繁
2023-03-14
问题内容

我正在阅读一本关于线程/同步的简单示例,该书声称使用synchronized会允许在同一实例上调用一个线程来访问该方法。它确实按照承诺进行了序列化,但似乎CallerSynch
main下面的方法中创建的第三个数组的大约9/10倍于第二个数组。该代码是示例代码,显示了没有同步方法的问题。

class CallMe {
    void call(String msg) {
        System.out.print("[" + msg);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("CallMe Interrupted");
        }
        System.out.println("]");
    }
}

class Caller implements Runnable {
    String msg;
    CallMe target;
    Thread t;

    public Caller (CallMe target, String msg) {
        this.target = target;
        this.msg = msg;
        t = new Thread(this);
        t.start();
    }

    @Override
    public void run() {
        target.call(msg);
    }
}

class Synch {
    public static void main(String args[]) {
        CallMe target = new CallMe();
        Caller c1 = new Caller(target, "Hello");
        Caller c2 = new Caller(target, "Synchronized");
        Caller c3 = new Caller(target, "World");

        try {       
            c1.t.join();
            c2.t.join();
            c3.t.join();        
        } catch (InterruptedException e) {
            System.out.println("Synch Interrupted");
        }
    }
}

这本书说明了两种方式来处理这个问题,他们是-
synchronized void call(String msg) {...}并且
public void run() { synchronized (target) {...} }

很显然,这两种选择工作,因为,相对于原来的代码,括号内的字都像一致…

[您好]
[世界](大约90%的电话回退时间)
[已同步](1 /许多已同步为第一个味精)

…原始代码没有韵律或理由。因此,我知道它是“有效的”,可以通过在每个Caller实例上放置断点直接看到它。每当我这样做时,对我来说,它每次都有效。

为什么第三个在第二个之前Caller始终调用call


问题答案:

根据定义,线程是并行运行的,并且没有任何优先级高于其他线程。

一旦线程全部启动,本质上是随机的,它将首先运行,通常,第一个启动的线程将具有轻微的“领先优势”,但是与启动线程等的开销相比,该优势很小。

您的特定环境的怪癖恰好偏向于使用一个线程,结果在不同的系统上可能会有所不同,因此当然不应该依赖它。

顺便说一句,这是不好的做法,原因有很多:

public Caller (CallMe target, String msg) {
    this.target = target;
    this.msg = msg;
    t = new Thread(this);
    t.start();
}

(实际上您可能会收到编译器警告)。

更好的是提供一种启动方法

public Caller start() {
    t.start();
    return this;
}

然后做

new Caller(target, msg).start();

这绝对可以确保Thread对象开始处理之前,Caller对象已完全初始化并准备就绪。



 类似资料:
  • 问题内容: 我有以下查询: 我有以下问题: USING语法与ON语法同义吗? 这些联接是从左到右评估的吗?换句话说,此查询是否说:x =公司加入了用户;y = x JOIN工作;z = y加入用户帐户; 如果对问题2的回答为“是”,那么可以安全地假设“公司”表中包含“公司ID”,“用户ID”和“工作ID”列? 我不明白在引用别名“ j”时,如何使用WHERE子句来选择公司表上的行 任何帮助,将不胜

  • 我有2个子项目的java项目。像这样的结构 我只需要在root buiild.gradle中创建'deploy'任务,然后执行以下操作: null 我看到错误“no-source”,但是文件夹“client/build/libs”和“server/build/libs”存在并包含jar。我可以肯定,因为手动运行任务‘复制文件’创建文件夹‘目标’和复制所有文件。我看到的唯一可能的选项是“复制文件”任

  • 问题内容: 原始问题: 当我的JavaScript调用的功能在页面下方而不是在调用页面的下方定义时,JSHint会抱怨。但是,我的页面是用于游戏的,在下载全部内容之前,不会调用任何函数。那么为什么订单功能出现在我的代码中很重要? 我在里面吟。看来我需要花另一天的时间才能重新排序六千行代码。使用javascript的学习曲线一点也不陡峭,但是非常糟糕。 问题答案: tl; dr 如果在加载完成之前不

  • 问题内容: 我担心给出的文件和目录的顺序。如果我有这些目录,,,,,,,,,,,,,什么是输出列表的顺序? 它是按数值排序的吗? 或按ASCII值排序,如? 此外,如何获得特定的排序? 问题答案: 用途。这是的文档字符串: listdir(路径)-> list_of_strings 返回一个列表,其中包含目录中条目的名称。 该列表按任意顺序排列 。它不包括特殊条目“。” 和“ ..”,即使它们存在

  • 问题内容: 我有一个导航栏作为地图: 其中具有各种属性,子项等。当我尝试渲染导航栏(带有)时,它以随机顺序显示。我知道它在运行时会随机排序,但是似乎无法获取有序的键列表或按插入顺序进行迭代。 游乐场链接位于此处:http : //play.golang.org/p/nSL1zhadg5,尽管它似乎没有表现出相同的行为。 如何在不破坏插入顺序的情况下迭代此映射? 问题答案: Go地图不保持插入顺序;

  • 我对Cumber框架没有什么顾虑:-1。我有一个功能文件(步骤相互依赖),我想按顺序运行所有场景,默认情况下它们是按随机顺序运行的。2.如何多次运行单个功能文件? 我贴上一些标签,试着跑,但没有运气。 因此,在上面的步骤中,我从一个步骤中获取令牌,并尝试在另一个步骤中打印令牌,但我得到的是null,而不是实际值,因为我的步骤是随机的。请注意,我正在通过testng运行TestRunner。xml文