干扰线程

时间:2013-02-11 16:56:19

标签: java multithreading

我对理解这段代码有疑问,我的问题是为什么在run方法执行语句期间两个线程不会相互干扰?

我的意思是,总是一个thead做所有语句然后是第二个线程来做声明。

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

注意:我知道这两个线程使用不同的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();
    }
}

尝试将System.out替换为out并比较结果然后您就会确切地知道我要求的是什么

2 个答案:

答案 0 :(得分:1)

解释前的几件事:

没有必要扩展Thread,并且更容易实现Runnable,它提供了您正在实施的run方法。此时,您可以将Runnable提供给Thread,或者更有用的是Executor(对于Java中的多线程非常有用)。

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

最后,您的代码不会共享任何内容,这就是为什么它们不会相互干扰的原因。每个人都打印出他们的名字和一个独特的字母,以便您可以找到它。 System.out在Sun实现中是线程安全的(正如Andre所指出的那样,技术上并不是JVM实现所必需的),因此您将无法中断输出,但这并不能阻止您进行交织输出。< / p>

例如,如果你运行足够,那么你可以很容易地看到:

thread 1 a
thread 2 a
thread 1 b
thread 2 b

但是,我怀疑你看到了:

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

这不是因为某些东西被破坏了,而是因为线程执行得如此之快以至于它就是这样发生的。由于您正在学习,最好在输出之间添加一些Thread.sleep调用随机延迟,这样您就可以有希望观察交织。

答案 1 :(得分:0)

System.out.println() out中也引用PrintStream 所以你在两种方式中调用相同的println()

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

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

现在想一想,out中的System.out.println是静态的,而PrintStream out则不是。{/ p>

PrintStream out=new PrintStream(System.out);

在上面的陈述中,out的新引用是非静态的。

  

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

因此,要获得所需的结果,请PrintStream out静态