Java 多线程代码行为

Posted

技术标签:

【中文标题】Java 多线程代码行为【英文标题】:Java Multithread code behavior 【发布时间】:2017-11-21 09:21:51 【问题描述】:

对于下面的java代码:

public class Chess implements Runnable 
    public void run() 
        move(Thread.currentThread().getId());
    

    void move(long id) 
        System.out.print(id + " ");
        System.out.print(id + " ");
    

    public static void main(String[] args) 
        Chess ch = new Chess();
        new Thread(ch).start();
        new Thread(new Chess()).start();
    

此代码的一个可能结果是 - 输出可能是 4 2 4 2(或者是 4、2 以外的其他线程 ID)。有人可以解释一下这是怎么可能的吗?鉴于线程将在“Chess”类的不同实例上运行,我们如何在此处打印不同的 id,因为两个 S.O.P 语句都立即打印 id,并且只有这两个线程会调用 move 方法

【问题讨论】:

我不明白你的问题。您启动了两个线程,每个线程都打印其 ID 两次,您想知道这两个 ID 中的每一个都可能打印两次吗? 输出可能是因为来自两个线程的System.out.print 语句可能交错。 尝试给线程名称,以便您理解。我相信正如安迪·特纳所说,线程交错运行。所以线程 ID: 4 执行,并且在 move() 完成之前,线程 id:2 执行。 您的 main() 例程创建了两个新的 Thread 实例。 Thread 类的构造函数保证每个实例都有自己的唯一 ID。 Thread.currentThread() 返回对运行调用它的代码的Thread 实例的引用。因此,调用Thread.currentThread().getId() 的两个不同线程会得到两个不同的数字也就不足为奇了。 【参考方案1】:

这并不奇怪。

您正在创建两个线程,每个线程都有不同的 id(在您的情况下分别为 2 和 4)。您将这些 id 打印两次,因此每个 id 都会打印两次。

现在解释不同的数字及其出现。

那么订单呢?好吧,这就是线程的问题,它们由处理器执行,您无法控制每条处理器指令的执行顺序。


PS:Chess 实例的数量无关紧要。如果您应该将代码更改为:

Chess ch = new Chess();
new Thread(ch).start();
new Thread(ch).start();

没关系。

【讨论】:

【参考方案2】:

“主”线程始终运行用户创建的线程。在您的情况下,“主”线程负责运行, new Thread(ch).start() //线程 - 0 新线程(新国际象棋()).start(); //线程 - 1.

由于上述线程具有相同的优先级(默认为 5),ThreadScehduler 将调度两个线程同时运行。因此,您会得到两个不同线程的 ID。

您可以在 Chess 类上同步并运行线程,然后您将一次打印一个线程 ID。

您可以按如下方式应用类级别锁定,并一次打印一个 ID,

public class Chess implements Runnable 
public void run() 
    move(Thread.currentThread().getId());


synchronized static void move(long id) 
    System.out.println(id + " ");
    System.out.println(id + " ");



public static void main(String[] args) 
    Chess ch = new Chess();
    new Thread(ch).start();
    new Thread(new Chess()).start();

【讨论】:

以上是关于Java 多线程代码行为的主要内容,如果未能解决你的问题,请参考以下文章

Java程序员必备!Java底层分析多线程行为附答案

多线程源码--Thread源码

python多线程库之threading

Python多线程

Java面试准备之多线程

Java多线程java中的Sleep方法