说一个经典的多线程问题:两个线程依次打印奇数、偶数,同时必须保证第一次打印的必须是奇数(即两个线程start顺序可以随意)。

解决方案 »

  1.   

    为你这问题单独写的一份代码public class OddEvenTest { public static void main(String[] args) {
    Object evenLock = new Object();
    Object oddLock = new Object();
    Thread even = new Thread(new EvenThread(evenLock, oddLock));
    Thread odd = new Thread(new OddThread(evenLock, oddLock));

    even.start();
    odd.start();

    try {
    // 等待even和odd线程都成功启动
    Thread.sleep(1000L);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    // 从奇数开始唤醒
    synchronized (oddLock) {
    oddLock.notify();
    }
    }
    }class OddThread implements Runnable { private Object oddLock;
    private Object evenLock; public OddThread(Object evenLock, Object oddLock) {
    this.evenLock = evenLock;
    this.oddLock = oddLock;
    } @Override
    public void run() {
    // TODO Auto-generated method stub
    try {
    for (int i = 1; i < 10;) {
    synchronized (oddLock) {
    oddLock.wait();
    }
    System.out.println(i);
    i = i + 2;
    synchronized (evenLock) {
    evenLock.notify();
    }
    }

    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } }}class EvenThread implements Runnable { private Object oddLock;
    private Object evenLock;

    public EvenThread(Object evenLock, Object oddLock) {
    this.evenLock = evenLock;
    this.oddLock = oddLock;
    }

    @Override
    public void run() {
    // TODO Auto-generated method stub
    try {
    for (int i = 2; i <= 10;) {
    synchronized (evenLock) {
    evenLock.wait();
    }
    System.out.println(i);
    i = i + 2;
    synchronized (oddLock) {
    oddLock.notify();
    }
    }

    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }}
      

  2.   


    class OutNumber implements Runnable
    {
    private int number=0;
    String firstName=null;
    public void run()
    {
    while(number<20) //输出20次。
    {
    synchronized(this)
    {
    if(number==0) //确定第一个进入的线称名.
    {
    firstName=Thread.currentThread().getName();
    System.out.println("first thread name is  "+firstName);
    number++;
    }
    else
    {
    //number 是奇数且是第一次输出的那个线程,则输出。
    if((number%2!=0)&&(Thread.currentThread().getName().equals(firstName)))
    {
    System.out.println("now the thread "+firstName+" is outputing the number\t"+(number++)%2);
    }
    //number 偶数且当前线程为另一线程,则由另一线程输出偶数。
    else if((number%2==0)&&!Thread.currentThread().getName().equals(firstName))
    {
    System.out.println("now the thread "+Thread.currentThread().getName()+
    " is outputing the number\t"+((number++)%2+2));
    }
    }
    }
    }
    }
    }public class TwoThread
    {
    public static void main(String[] rags)
    {
    OutNumber outNumber=new OutNumber();
    Thread t1=new Thread(outNumber,"A");
    Thread t2=new Thread(outNumber,"B");
    t1.start();
    t2.start();
    }
    }first thread name is  B
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
    now the thread B is outputing the number        1
    now the thread A is outputing the number        2
      

  3.   


    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;public final class PrintThread {
    private static final int THREAD_NUMBER = 2; /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
    ExecutorService service = null;
    try {
    service = Executors.newFixedThreadPool(THREAD_NUMBER);
    List<PrintTask> tasks = new ArrayList<PrintTask>(2);
    tasks.add(new PrintTask(true));
    tasks.add(new PrintTask(false));
    service.invokeAll(tasks);
    service.awaitTermination(1, TimeUnit.HOURS);
    } finally {
    if (service != null) {
    service.shutdown();
    }
    }
    } static class PrintTask implements Callable<Object> {
    private boolean isPrintEven;
    private static volatile boolean isFirst = true;
    private static final ReentrantLock lock = new ReentrantLock();
    private static final Condition printEven = lock.newCondition();
    private static final Condition printOdd = lock.newCondition(); public PrintTask(boolean _isPrintEven) {
    this.isPrintEven = _isPrintEven;
    } /**
     * execute the print function
     */
    public Object call() throws Exception {
    while (true) {
    lock.lock();
    try {
    if (isPrintEven) {
    printOdd.signal();
    printEven.await();
    System.out.println("Even number..");
    } else {
    if (!isFirst) {
    printEven.signal();
    printOdd.await();
    } else {
    isFirst = false;
    }
    System.out.println("Odd number..");
    }
    } catch (Exception ex) {
    System.out.println("Exception occurred, ex message:"
    + ex.getMessage());
    } finally {
    lock.unlock();
    }
    Thread.sleep(10);
    }
    }
    }
    }
      

  4.   

    public class Test {
    private static int number = 1;
    private static boolean first = true;
    public static void main(String[] args) {
    final Test test = new Test();
    Thread odd = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 50; i++) {
    test.print();
    }

    }
    });

    Thread even = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 50; i++) {
    test.print();
    }
    }
    });


    odd.setName("odd");
    even.setName("even");
    even.setDaemon(true);
    even.start();
    odd.start();
    }

    public synchronized void print() {
    if (first) {
    if ("odd".equalsIgnoreCase(Thread.currentThread().getName())) {
    first = false;
    } else {
    this.notify();
    try {
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    System.out.println("执行线程为" + Thread.currentThread().getName() + ":" + number++);
    this.notify();
    try {
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
      

  5.   

    public class Test {
    private static int number = 1;
    private static boolean first = true;
    public static void main(String[] args) {
    final Test test = new Test();
    Thread odd = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 50; i++) {
    test.print();
    }

    }
    });

    Thread even = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 50; i++) {
    test.print();
    }
    }
    });


    odd.setName("odd");
    even.setName("even");
    even.setDaemon(true);
    even.start();
    odd.start();
    }

    public synchronized void print() {
    if (first) {
    if ("odd".equalsIgnoreCase(Thread.currentThread().getName())) {
    first = false;
    } else {
    this.notify();
    try {
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    System.out.println("执行线程为" + Thread.currentThread().getName() + ":" + number++);
    this.notify();
    try {
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
      

  6.   

    也写一个玩儿:
    package com.test;/**
     * 两个线程依次打印奇数、偶数, 同时必须保证第一次打印的必须是奇数 (即两个线程start顺序可以随意)。
     * 
     */
    public class Test
    {
    public static void main(String[] args)
    {
    Print p = new Print();
    new Thread(new OuPrint(p)).start();
    new Thread(new JiPrint(p)).start();
    }
    }class Print
    {
    private int a = 1;

    synchronized void print1()
    {
    try
    {
    while (0 == a % 2)
    {
    wait();
    }
    Thread.sleep((long) (Math.random() * 500));
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }

    System.out.println("Ji : " + a++);
    notify();
    }

    synchronized void print2()
    {
    try
    {
    while (0 != a % 2)
    {
    wait();
    }
    Thread.sleep((long) (Math.random() * 500));
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }

    System.out.println("Ou : " + a++);
    notify();
    }
    }class JiPrint implements Runnable
    {
    private Print p;

    JiPrint(Print p)
    {
    this.p = p;
    }

    @Override
    public void run()
    {
    while (true)
    p.print1();
    }
    }class OuPrint implements Runnable
    {
    private Print p;

    OuPrint(Print p)
    {
    this.p = p;
    }

    @Override
    public void run()
    {
    while (true)
    p.print2();
    }
    }
      

  7.   

    看不出这问题怎么个经典法了?如果是顺序输出,那为什么要使用多线程?如果用多线程这样轮流着 notify 和 wait 带来线程切换的开销你知道有多大么?
      

  8.   

    上面大家都写代码贴代码了,我就不再贴代码了。某意思。只是想说的是,学习线程最经典还是要数大学里学到的生产者与消费者之间的关系以及十字路口的代码。你有机会可以看一下。如需其他帮助和支持。欢迎加入我们的java开发联盟。
    群号:
       247286682
    来者请注明csdn.