Java 干扰线程

Java 干扰线程,java,multithreading,Java,Multithreading,我在理解这段代码时遇到了一个问题,我的问题是为什么这两个线程在执行run方法中的语句时不会相互干扰 我的意思是,所有的语句都是先执行,然后再执行第二个线程 第一个线程执行语句的一部分,然后第二个线程执行语句的一部分,然后第一个线程继续其任务是不可能的 注意:我知道这两个线程使用不同的OutputStream对象 这里的线程代码 class Printer extends Thread { private String ThreadName; public Printer(Strin

我在理解这段代码时遇到了一个问题,我的问题是为什么这两个线程在执行
run
方法中的语句时不会相互干扰

我的意思是,所有的语句都是先执行,然后再执行第二个线程

第一个线程执行语句的一部分,然后第二个线程执行语句的一部分,然后第一个线程继续其任务是不可能的

注意:我知道这两个线程使用不同的
OutputStream
对象

这里的线程代码

class Printer extends Thread
{
   private String ThreadName;

   public Printer(String name)
   {
       this.ThreadName=name;
   }

   public void run()
   {
       PrintStream out=new PrintStream(System.out);

       out.println(this.ThreadName+" : a");
       out.println(this.ThreadName+" : b");
       out.println(this.ThreadName+" : c");
       out.println(this.ThreadName+" : d");
       out.println(this.ThreadName+" : e");
       out.println(this.ThreadName+" : f");
       out.println(this.ThreadName+" : g");
       out.println(this.ThreadName+" : h");
       out.println(this.ThreadName+" : i");
       out.println(this.ThreadName+" : j");
       out.println(this.ThreadName+" : k");    
   }
}
入境代码:

class Main 
{
    public static void main(String[] args)
    {
        Thread t1 = new Printer("thread 1");
        Thread t2 = new Printer("thread 2");

        t1.start();
        t2.start();
    }
}

试着用
out
替换
System.out
,并比较结果,然后你就会确切地知道我要的是什么

在解释之前有几件事:

不需要扩展
线程
,只需实现
可运行
,它提供了您正在实现的
运行
方法,就更容易了。此时,您可以将
Runnable
分配给
线程
,或者更有用的是,分配给
执行器(对于Java中的多线程非常有用)

此外,在
PrintStream
中包装也是多余的,因为
System.out
本身已经是
PrintStream

最后,您的代码没有共享任何内容,这就是它们不相互干扰的原因。每个人所做的就是打印出他们的名字和一个独特的字母,这样你就可以找到它
System.out
在Sun实现中是线程安全的(正如Andre所指出的,JVM实现在技术上并不要求这样),因此您将无法分解输出,但这并不会阻止您潜在地交织输出

例如,如果运行足够多,则可以很容易地看到:

thread 1 a
thread 2 a
thread 1 b
thread 2 b
但是,我怀疑您正在看到:

thread 1 a
    .
    .
    .
thread 1 k
thread 2 a
    .
    .
    .
thread 2 k

这并不是因为有什么东西坏了,而是因为线程执行得太快了,所以就这样发生了。由于您正在学习,因此最好在输出之间添加一些
线程。随机延迟的sleep
调用,以便您能够有希望地观察交织情况。

在解释之前有几件事:

不需要扩展
线程
,只需实现
可运行
,它提供了您正在实现的
运行
方法,就更容易了。此时,您可以将
Runnable
分配给
线程
,或者更有用的是,分配给
执行器(对于Java中的多线程非常有用)

此外,在
PrintStream
中包装也是多余的,因为
System.out
本身已经是
PrintStream

最后,您的代码没有共享任何内容,这就是它们不相互干扰的原因。每个人所做的就是打印出他们的名字和一个独特的字母,这样你就可以找到它
System.out
在Sun实现中是线程安全的(正如Andre所指出的,JVM实现在技术上并不要求这样),因此您将无法分解输出,但这并不会阻止您潜在地交织输出

例如,如果运行足够多,则可以很容易地看到:

thread 1 a
thread 2 a
thread 1 b
thread 2 b
但是,我怀疑您正在看到:

thread 1 a
    .
    .
    .
thread 1 k
thread 2 a
    .
    .
    .
thread 2 k

这并不是因为有什么东西坏了,而是因为线程执行得太快了,所以就这样发生了。由于您正在学习,最好在输出之间添加一些
线程。睡眠
随机延迟调用,这样您就可以有希望地观察到交织。

in
System.out.println()
out
也是
PrintStream
因此,您以两种方式调用相同的
println()

但你得到的是不同的输出。虽然println函数有同步实现

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}
现在想想,
System.out.println
中的
out
是静态的,而
PrintStream out
不是

PrintStream out=new PrintStream(System.out);
在上面的语句中,
out
的新引用是非静态的

如果方法不是静态的,那么添加synchronized关键字将 同步类的实例,而不是类对象


因此,为了获得所需的结果,在
System.out.println()中制作
PrintStream out
static

out
也是
PrintStream
因此,您以两种方式调用相同的
println()

但你得到的是不同的输出。虽然println函数有同步实现

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}
现在想想,
System.out.println
中的
out
是静态的,而
PrintStream out
不是

PrintStream out=new PrintStream(System.out);
在上面的语句中,
out
的新引用是非静态的

如果方法不是静态的,那么添加synchronized关键字将 同步类的实例,而不是类对象


因此,为了得到您想要的结果,请整理一下您的代码样本。到目前为止,您有研究过什么吗?您发现了什么?当您运行它们时,它们不会干扰这一事实并不意味着它们通常不会干扰(例如,在另一台计算机上运行,在不同的情况下运行等)。当我运行代码时,当打印另一个线程的输出时,第一个线程的输出通常在换行之前“暂停”。当重复运行程序时,每次都会得到不同的输出。我对答案的最佳猜测是“因为调度程序就是这样选择运行它们的”。这可能还与他们都试图阻止相同的资源(
System.out
)有关,我认为这可能是同步的