使用2个不同的类别打印偶数和奇数

时间:2014-06-16 15:59:53

标签: java multithreading thread-synchronization

这是我在求职面试中提出的一个问题:

你有两个不同的类(实现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个同步方法。

请问任何专家建议吗?

3 个答案:

答案 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();

    }
}

}