小编典典

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

java

我正在阅读一本关于线程/同步的简单示例,该书声称使用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


阅读 189

收藏
2020-11-26

共1个答案

小编典典

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

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

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

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

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对象已完全初始化并准备就绪。

2020-11-26