这是我在求职面试中提出的一个问题:
你有两个不同的类(实现Runnable)说EvenThread& OddThread。顾名思义,EvenThread只打印偶数,而奇数线程只打印奇数,考虑范围为0-100。
class EvenThread implements Runnable {
@Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
System.out.println(i);
}
}
}
class OddThread implements Runnable {
@Override
public void run() {
for (int i = 1; i < 10; i += 2) {
System.out.println(i);
}
}
}
public class EvenOdd {
public static void main(String args[]) {
Thread tEven = new Thread(new EvenThread());
Thread tOdd = new Thread(new OddThread());
tEven.start();
tOdd.start();
}
}
现在我们需要以这样一种方式强制执行机制:数字按顺序打印(即0,1,2,3,4 ......等等)。
我在Stack Overflow中看到了很多类似的问题,但它们只有一个类来打印数字,并且在其中调用了2个同步方法。
请问任何专家建议吗?
答案 0 :(得分:4)
这是一个带有低级别等待/通知机制的丑陋示例:
public class Main {
static boolean turn = false; // false is even, true is odd
public static void main(String[] args) {
Object o = new Object();
Thread tEven = new Thread(new EvenThread(o));
Thread tOdd = new Thread(new OddThread(o));
tEven.start();
tOdd.start();
}
// TODO some inheritance with [Even/Odd]Thread
static class EvenThread implements Runnable {
Object o;
EvenThread(Object o) {
this.o = o;
}
@Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
synchronized (o) {
try {
while (turn) {
o.wait();
}
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
finally {
System.out.println(i);
turn = !turn;
o.notifyAll();
}
}
}
}
}
static class OddThread implements Runnable {
Object o;
OddThread(Object o) {
this.o = o;
}
@Override
public void run() {
for (int i = 1; i < 10; i += 2) {
synchronized (o) {
try {
while (!turn) {
o.wait();
}
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
finally {
System.out.println(i);
turn = !turn;
o.notifyAll();
}
}
}
}
}
}
<强>输出强>
0
1
2
3
4
5
6
7
8
9
10
答案 1 :(得分:1)
不能直接回答您的问题,只是为了表明您并不总是需要锁定或同步 - memory barrier就足够了。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class EvenAndOdd implements Runnable {
public static final int MAX_RUNTIME_SECONDS = 3;
public static void main(String[] args) {
ExecutorService tp = Executors.newCachedThreadPool();
AtomicInteger counter = new AtomicInteger();
tp.execute(new EvenAndOdd(counter, true));
//try { Thread.sleep(500); } catch (Exception ignored) {}
tp.execute(new EvenAndOdd(counter, false));
tp.shutdown();
boolean tpTerminated = false;
try {
if (tp.awaitTermination(MAX_RUNTIME_SECONDS, TimeUnit.SECONDS)) {
tpTerminated = true;
System.out.println("Finished.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (!tpTerminated) {
System.out.println("Forcing shutdown.");
tp.shutdownNow();
}
}
}
public static final int MAX_COUNTER = 10;
private final boolean odd;
private final AtomicInteger counter;
public EvenAndOdd(AtomicInteger counter, boolean odd) {
this.odd = odd;
this.counter = counter;
}
@Override
public void run() {
int emptyCycleCounter = 0;
while (true) {
int i = counter.get();
if (i > MAX_COUNTER) {
break;
}
if (i % 2 == (odd ? 1 : 0)) {
System.out.println(i + (odd ? " odd" : " even"));
counter.incrementAndGet();
} else {
emptyCycleCounter++;
Thread.yield();
}
}
System.out.println("Finished" + (odd ? " odd" : " even") + " with " + emptyCycleCounter + " empty cycles.");
}
}
答案 2 :(得分:0)
公共类MyLock {
public MyLock(Boolean even) {
super();
this.even = even;
}
static Boolean even = null;
public synchronized void lock(boolean value) {
while (even != value) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized void unlock() {
even = !even;
notify();
}
}
公共课OddEven {
private static final int Max_CCOUNTER = 100;
static final MyLock lock = new MyLock(true);
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(() -> printEven(), "EVEN").start();
;
new Thread(() -> printOdd(), "ODD").start();
;
}
static void printEven() {
for (int i = 0; i < Max_CCOUNTER; i = i + 2) {
lock.lock(true);
System.out.println(i + ":" + Thread.currentThread().getName());
lock.unlock();
}
}
static void printOdd() {
for (int i = 1; i < Max_CCOUNTER; i = i + 2) {
lock.lock(false);
System.out.println(i + ":" + Thread.currentThread().getName());
lock.unlock();
}
}
}