2013-04-12 87 views
2

使用两个线程,您应该打印“Hello World Hello World Hello World Hello World Hello World Hello World Hello World”。多线程Hello World

在两个线程一个应打印“你好:和另一个线程的‘世界’

我可以用不同的类,如每一个对你好,世界 做到这一点我也可以用内部类

做到这一点。

有没有一种方法,使得只有一个主类,并没有内部类的?

+1

是;使用类中的字段并创建两个实例。 – SLaks

+1

让您的班级成为您可以传递“String”的“Runnable”。 –

回答

3

有没有一种方法,使得只有一个主类,并没有内部类的?

当然。您可以传入字符串以打印到您的Main类中。当然棘手的部分是协调线程,所以他们实际上打印出"HelloWorld"而不是"WorldHello"或其他排列。线程将并行运行,不保证顺序。这就是线程化程序的重点 - 它们是异步运行的。试图强制某个字输出否定了使用线程的目的。

<rant>这给我一个设计不好的计算机科学任务。使用线程编写的全部要点是它们可以独立并行运行。当每个线程从工作队列中拉出,然后将结果放入结果队列或某物时,通常会发生协调。任何时候你有一个需要协调的线程程序,你很可能不会使用线程。 < /咆哮>

但是,因为每个人都在向下投票我以前的答案很可能是因为它不能很好地解决他们的家庭作业的问题,我会添加一些逻辑的两个线程之间的协调和吐出的“Hello World。 ..“。

这两个线程需要能够锁定某些东西,互相发信号并知道他们应该等待还是打印。因此,我将添加一个boolean printHello并锁定传入的常见锁定对象:

public class HelloWorld implements Runnable { 

    private static boolean printHello = true; 

    private final String toPrint; 
    private final boolean iPrintHello; 
    private final Object lock; 

    public static void main(String[] args) { 
     final Object lock = new Object(); 
     // first thread prints Hello 
     new Thread(new HelloWorld("Hello ", true, lock)).start(); 
     // second one prints World 
     new Thread(new HelloWorld("World ", false, lock)).start(); 
    } 

    public HelloWorld(String toPrint, boolean iPrintHello, Object lock) { 
     this.toPrint = toPrint; 
     this.iPrintHello = iPrintHello; 
     this.lock = lock; 
    } 

    @Override 
    public void run() { 
     // don't let it run forever 
     for (int i = 0; i < 1000 && !Thread.currentThread().isInterrupted();) { 
      // they need to synchronize on a common, constant object 
      synchronized (lock) { 
       // am I printing or waiting? 
       if (printHello == iPrintHello) { 
        System.out.print(toPrint); 
        // switch the print-hello to the other value 
        printHello = !printHello; 
        // notify the other class that it can run now 
        lock.notify(); 
        i++; 
       } else { 
        try { 
         // wait until we get notified that we can print 
         lock.wait(); 
        } catch (InterruptedException e) { 
         // if thread is interrupted, _immediately_ re-interrupt it 
         Thread.currentThread().interrupt(); 
         return; 
        } 
       } 
      } 
     } 
    } 
} 
+0

评论是非常有帮助的。任何'lock'传入的线程对象都被同步到它,这意味着它('lock')将在线程可以运行时管理。如果有3个线程呢?有没有办法我也可以指定线程?我查看了'notify()'文档,它说默认选择下一个线程,并且没有重载的方法。 – Abdul

+0

如果有超过1个线程,你可以调用'notifyAll()',它们都会醒来,看看它们是否应该打印@Abdul。我真的很讨厌使用'notifyAll()',因为通常任何线程都应该能够处理,但在这个奇怪的例子中,它可以工作。 – Gray

1

这个怎么样?没有线程都有一个特定的词,但在使用一对夫妇的Atomic的:这就像具体责任容易确保螺纹处于锁定状态。

这个算法并不依赖于只有两个步骤 - 正如你可以看到它仍然适用于任何数量的线程,在这种情况下,42。它仍然会很好地工作刚2,甚至1

public class HelloWorld implements Runnable { 
    // The words. 
    private final String[] words; 
    // Which word to print next. 
    private final AtomicInteger whichWord; 
    // Cycles remaining. 
    private final AtomicInteger cycles; 

    private HelloWorld(String[] words, AtomicInteger whichWord, AtomicInteger cycles) { 
    // The words to print. 
    this.words = words; 
    // The Atomic holding the next word to print. 
    this.whichWord = whichWord; 
    // How many times around we've gone. 
    this.cycles = cycles; 
    } 

    @Override 
    public void run() { 
    // Until cycles are complete. 
    while (cycles.get() > 0) { 
     // Must transit from this word 
     int thisWord = whichWord.get(); 
     // to the next word. 
     int nextWord = thisWord + 1; 
     // Are we cycling? 
     boolean cycled = false; 
     if (nextWord >= words.length) { 
     // We cycled! 
     cycled = true; 
     // Back to zero. 
     nextWord = 0; 
     } 
     // Grab hold of System.out to ensure no race there either. 
     synchronized (System.out) { 
     // Atomically step the word number - must still be at thisWord for the step calculations to still be correct. 
     if (whichWord.compareAndSet(thisWord, nextWord)) { 
      // Success!! We are the priveliged one! 
      System.out.print(words[thisWord]); 
      // Count the cycles. 
      if (cycled) { 
      // Just step it down. 
      cycles.decrementAndGet(); 
      } 
     } 
     } 
    } 
    } 

    public static void test() throws InterruptedException { 
    // The words to print. 
    String [] words = {"Hello ", "world. "}; 
    // Which word to print next (start at 0 obviously). 
    AtomicInteger whichWord = new AtomicInteger(0); 
    // How many cycles to print - 6 as specified. 
    AtomicInteger cycles = new AtomicInteger(6); 
    // My threads - as many as I like. 
    Thread [] threads = new Thread[/*2*/42]; 
    for (int i = 0; i < threads.length; i++) { 
     // Make each thread. 
     threads[i] = new Thread(new HelloWorld(words, whichWord, cycles)); 
     // Start it. 
     threads[i].start(); 
    } 
    // Wait for them to finish. 
    for (int i = 0; i < threads.length; i++) { 
     // Wait for completion. 
     threads[i].join(); 
    } 
    } 

    public static void main(String args[]) throws InterruptedException { 
    System.out.println("HelloWorld:Test"); 
    test(); 
    } 

} 
+0

呃,哇。这当然是一种方法。你错过了整合磁通电容器。 :-) – Gray

+1

@Gray - 添加助熔剂电容会使'原子'超载。 – OldCurmudgeon

0
  1. 如果你想要那个T1打印“Hello”和T2打印“世界”,和你预期的结果是“你好,世界你好你好世界世界Hello World世界你好世界你好世界“

    T1有第一个开始,T2被T1调用,否则你可以有”World Hello Hello World“作为输出。

    我建议使用notify()notifyAll()方法来唤醒其他线程来定制读写器或生产者/消费者结构。

  2. 如果您不关心输出格式,请使用Runnable接口和您的首选实现。