System.out.printf()语句是异步的吗?

我打印信息以使用重入锁测试线程。 我使用语句new ReentrantLock(true)创建公平锁。

在我使用锁的对象方法之一,我正在使用方法,例如

method() { for (int n = 0; n < 3; n++) { System.out.printf("%s: processing data \n", Thread.currentThread().getName(), data.get()); TimeUnit.SECONDS.sleep(1); } } 

我正在创建10个线程,所有线程应执行相同的语句3次执行此控制台print语句。 但是,我没有得到输出,我看到每个线程以相同的顺序显示打印。 例如

 Thread 1: processing data hjjjj Thread 2: processing data ghhjj Thread 3: processing data uiyiii Thread 2: processing data ghfrtu ...... ...... 

而我的期望如下:

 Thread 1: processing data hjjjj Thread 2: processing data ghhjj Thread 3: processing data uiyiii Thread 1: processing data uiyuii 

是因为公平性在起作用,但system.out.println的打印顺序与打印命令的顺序不一样?

这是我的课程..

 public class PriceInfo { private double price1 =1d, price2=2d; ReadWriteLock lock = new ReentrantReadWriteLock(true); public double getPrice1() { lock.readLock().lock(); try{ return price1; }finally{ lock.readLock().unlock(); } } public double getPrice2() { lock.readLock().lock(); try{ return price2; }finally{ lock.readLock().unlock(); } } public void getPrices() { lock.readLock().lock(); try{ synchronized (System.out) { System.out.printf("%s: price1 = %f and price2 = %f \n", Thread.currentThread().getName(), price1, price2); System.out.flush(); } }finally{ lock.readLock().unlock(); } } public void setPrices(double p1, double p2) { lock.writeLock().lock(); try{ System.out.println(Thread.currentThread().getName() + ": starting to set new prices "); price1 = p1; price2 = p2; System.out.println(Thread.currentThread().getName() + ": prices changed to price1:"+ p1 + "price2: "+ p2); }finally{ lock.writeLock().unlock(); } } } 

现在还有另一个class..

 public class Reader implements Runnable { private PriceInfo info; public Reader(PriceInfo inf) { info = inf; } @Override public void run() { for (int i=0; i<2; i++) { info.getPrices(); } } } 

最后,我们有编写线程和主类。

 public class Writer implements Runnable{ private PriceInfo info; public Writer(PriceInfo inf) { info = inf; } @Override public void run() { for (int i=0; i<2; i++) { info.setPrices(new Double(Math.random()*10).doubleValue(), new Double(Math.random()*9).doubleValue()); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { PriceInfo pricesInfo=new PriceInfo(); // create 5 threads and 5 readers Reader readers[]=new Reader[5]; Thread threadsReader[]=new Thread[5]; for (int i=0; i<5; i++){ readers[i]=new Reader(pricesInfo); threadsReader[i]=new Thread(readers[i],("Thread" + i)); } // create writer thread Writer writer=new Writer(pricesInfo); Thread threadWriter=new Thread(writer,"WriterThread"); for (int i=0; i<5; i++){ threadsReader[i].start(); } threadWriter.start(); } } 

我得到以下输出..

  Thread0: price1 = 1.000000 and price2 = 2.000000 Thread4: price1 = 1.000000 and price2 = 2.000000 Thread3: price1 = 1.000000 and price2 = 2.000000 Thread2: price1 = 1.000000 and price2 = 2.000000 Thread1: price1 = 1.000000 and price2 = 2.000000 WriterThread: starting to set new prices WriterThread: prices changed to price1:3.971662648848391price2: 8.604830021768233 Thread0: price1 = 3.971663 and price2 = 8.604830 Thread1: price1 = 3.971663 and price2 = 8.604830 Thread2: price1 = 3.971663 and price2 = 8.604830 Thread3: price1 = 3.971663 and price2 = 8.604830 Thread4: price1 = 3.971663 and price2 = 8.604830 WriterThread: starting to set new prices WriterThread: prices changed to price1:3.0036555312769297price2: 5.15672274505239 

所以,你可以看到执行的线程序列是thread0,thread4,3,2,1,writer,0,1,2,3,4,而我期望按照公平的策略,我们应该有相同的序列,如0 ,4,3,2,1 0,4,3,2,1。

我的代码有问题还是公平政策不严格?

我正在创建10个线程,所有线程应执行相同的语句3次执行此控制台print语句。 但是,我没有得到输出,我看到每个线程以相同的顺序显示打印。 例如

一个特定的输出序列很难(和不必要)来获得线程。 System.out.printf(...)是一个同步操作,因此输出永远不会相互重叠,但由于一次运行多个线程所固有的竞争条件,输出行的顺序是不可预测的。 就异步 (与线程同步无关)而言,默认情况下, System.out启用了自动刷新,因此每次写入都会刷新对PrintStream所有写入。

线程应用程序的特定输出顺序是FAQ。 在这里查看我的答案: multithreading中的不需要的输出

从答案中引用,由于硬件,竞争条件,时间切片随机性和其他因素,无法预测线程运行的顺序。

System.out是一个缓冲流。 这意味着它不会同步填充控制台。 printf()调用是同步的,而控制台输出则不是。

你可以:

  • 通过调用System.out.flush(); flush()System.out System.out.flush();
  • 使用println()自动刷新流,
  • 使用不是AFAIK缓冲的System.err

不确定最后一个……

请注意,您的线程是并发执行的(如果您使用.start() )这意味着您不能指望没有同步元素的任何执行顺序。

虽然很难在没有看到代码启动线程的情况下回答这个问题,但这似乎与System.out.printf()的行为没有任何关系。 您正在启动的线程彼此独立地唤醒和hibernate,因此线程之间打印的行的顺序取决于运行代码的JVM。 如果您需要按顺序使用语句,但想要并行完成工作,可以使用CyclicBarrier来协调print语句。