0

有2个线程一个打印{1,3,5,7,9}。另一个打印{2,4,6,8,10}

我想打印 {1,2,3,4,5,6,7...}

package com.oddnumber.threading;

public class NumberPrint implements Runnable {
  int number=1;
  private Object lock = new Object();
  private volatile boolean isOdd = false;

  public void generateEvenNumbers(int number) throws InterruptedException {
    synchronized (lock) {
      while (isOdd == false) {
        lock.wait();
      }
      System.out.println("even" + number);
      isOdd = false;
      lock.notifyAll();
    }
  }

  public void generateOddNumbers(int number) throws InterruptedException {
    synchronized (lock) {
      while (isOdd == true) {
        lock.wait();
      }
      System.out.println("odd" + number);
      isOdd = true;
      lock.notifyAll();
    }
  }

  @Override
  public void run() {
    while(true) {
      if(number%2 == 0) {
        try {
          generateEvenNumbers(number);
          number++;
          Thread.sleep(1112);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } else {
        try {
          generateOddNumbers(number);
          number++;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }     
}

我已经使用:

package com.oddnumber.threading;
public class Test
{
  public static void main(String[] args) {
    NumberPrint n1 = new NumberPrint();
    NumberPrint n2 = new NumberPrint();
    new Thread(n1).start();
    new Thread(n2).start();
  }
}

输出:

 1
 1
 2
 2
 3
 3
 4
 4
 5
 5
 6
 6
 7
 8
 7
 8
 9
 9
 10

每个数字打印两次,但是为什么两个线程之间不共享数字变量?

4

4 回答 4

4

NumberPrint 类的每个实例都有自己的锁对象实例。在两个不同的实例上使用同步将没有效果。这些方法必须使用相同的对象。一种方法是 main() 方法创建一个对象的实例并将其传递给 NumberPrint 构造函数,以便所有方法都使用一个实例来同步。

于 2013-08-27T16:37:01.300 回答
0

正如 NormR 所说,两个线程必须共享同一个锁,例如:

public class Main {

    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();

        Thread evenThread = new Thread(new GeneratorHandler(lock, new EvenGenerator()));
        Thread oddThread = new Thread(new GeneratorHandler(lock, new OddGenerator()));

        oddThread.start();
        Thread.sleep(500);
        evenThread.start();

    }

}

public interface Generator {
    public int generate();
}

public class EvenGenerator implements Generator {
    int n = 0;

    @Override
    public int generate() {
        return n += 2;
    }
}

public class OddGenerator implements Generator {
    int n = -1;

    @Override
    public int generate() {
        return n += 2;
    }
}

public class GeneratorHandler implements Runnable {

    private Object lock;
    private Generator generator;

    public GeneratorHandler(Object lock, Generator generator) {
        this.lock = lock;
        this.generator = generator;
    }

    @Override
    public void run() {
        while (true) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized(lock){
                System.out.println(generator.generate());
            }


        }
    }

}
于 2013-08-27T17:11:07.973 回答
0

首先,您需要在NumberPrint static(并且可能static volatile)中创建变量,以便它们将在两个线程之间共享。这应该为numberlock和完成isOdd。但是,如果这就是您所做的一切,那么您的输出将是 {1, 2, 1, 4, 5, 6, 7, 8, ...} 因为这两个线程在number开始运行时都尽可能快地读取,没有任何同步。最好的解决方案似乎是确保在它们同步generateEvenNumbersgenerateOddNumbers读取共享number文件——这意味着去掉number这些例程的参数,然后当他们读取number时,它将是共享的。

于 2013-08-27T16:26:26.590 回答
0
    public class PrintOnetoTen {

    public static void main(String[] args) {

            SharedPrinter sp = new SharedPrinter();

            ExecutorService executor = Executors.newFixedThreadPool(2);
            executor.submit(new EvenNumberProducer(sp, 10));
            executor.submit(new OddNumberProducer(sp , 10));
            executor.shutdown();
        }

    }


    class SharedPrinter {

        Semaphore semEven = new Semaphore(0);
        Semaphore semOdd = new Semaphore(1);

        public void printEvenNumber(int num) {
            try {
                semEven.acquire();
            }catch(InterruptedException exception) {

            }
            System.out.println("Thread 2 - Number : " +num);
            semOdd.release();
        }

        public void printOddNumber(int num) {
            try {
                semOdd.acquire();
            }catch(InterruptedException exception) {

            }
            System.out.println("Thread 1 - Number : " +num);
                semEven.release();
        }

    }

    class EvenNumberProducer implements Runnable {

        SharedPrinter sp;
        int index;

        EvenNumberProducer(SharedPrinter sp , int index) {
            this.sp = sp;
            this.index = index;
        }

        @Override
        public void run() {
            for(int i = 2 ; i <= index ; i = i + 2 ) {
                sp.printEvenNumber(i);
            }
        }
    }

    class OddNumberProducer implements Runnable{
        SharedPrinter sp;
        int index;

        OddNumberProducer(SharedPrinter sp , int index) {
            this.sp = sp;
            this.index = index;
        }

        @Override
        public void run() {
            for(int i = 1 ; i <= index ; i = i + 2) {
                sp.printOddNumber(i);
            }
        }
    }

程序的输出是:

    Thread 1 - Number : 1

    Thread 2 - Number : 2

    Thread 1 - Number : 3

    Thread 2 - Number : 4

    Thread 1 - Number : 5

    Thread 2 - Number : 6

    Thread 1 - Number : 7

    Thread 2 - Number : 8

    Thread 1 - Number : 9

    Thread 2 - Number : 10
于 2019-09-21T15:24:22.930 回答