使用两个线程你应该打印“Hello World Hello World Hello World Hello World Hello World Hello World”。
在两个主题中,应该打印“Hello:和另一个主题”World“。
我可以用不同的类来做到这一点,例如hello和world各一个 我也可以用内部类
来做有没有一种方法,只有一个主类而且没有内部类?
答案 0 :(得分:4)
有没有一种方法,只有一个主类而且没有内部类?
不确定。您可以传入字符串以打印到Main类中。当然,棘手的部分是协调线程,以便它们实际打印出"HelloWorld"
而不是"WorldHello"
或其他排列。线程将并行运行,不保证顺序。这是线程程序的全部意义 - 它们以异步方式运行。试图强制使用特定的单词输出会否定使用线程的目的。
<咆哮>这让我想起了一个设计糟糕的计算机科学任务。使用线程编写的全部内容是它们并行独立运行。协调通常发生在每个线程从工作队列中拉出然后将结果放入结果队列或其他内容时。任何时候你有一个需要协调这么多的线程程序,你很可能不会使用线程。 < /咆哮>
但是,既然每个人都投票给我以前的答案可能是因为它没有完美地解决他们的作业问题,我会添加一些逻辑来协调两个线程并吐出“Hello World ......”。 / p>
这两个线程需要能够锁定某些东西,相互发出信号,并知道它们何时应该等待或打印。所以我将添加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;
}
}
}
}
}
}
答案 1 :(得分:1)
这看起来怎么样?没有线程对特定单词负有特定责任,但是使用几个Atomic
s很容易确保线程处于锁定状态。
这个算法不依赖于只有两个踏板 - 你可以看到它仍适用于任意数量的线程,在这种情况下为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();
}
}
答案 2 :(得分:0)
如果您希望T1打印“Hello”而T2打印“World”,您的预期结果为“Hello World Hello World Hello World Hello World Hello World Hello World”
T1首先启动,T1由T1调用,否则可以输出“World Hello Hello Hello World”。
我建议使用notify()
或notifyAll()
方法来自定义读者/编写者或生产者/消费者结构,以唤醒其他线程。
如果不注意输出格式,请使用Runnable接口和首选实现。