简体   繁体   English

使用相同类别的两个线程(偶数和奇数)打印1-1000

[英]Print 1-1000 with two threads (even and odd) from the same class

So my task is this: 所以我的任务是这样的:

  1. Instantiate two object of the same class 实例化同一类的两个对象

  2. Provide a constructor argument, to designate a thread as even and another as odd . 提供构造函数参数,以将线程指定为偶数,将另一个指定为奇数。

  3. Start both threads right one after other 一个接一个地启动两个线程

  4. Odd thread prints odd numbers from 0 to 1000 奇数线程打印从0到1000的奇数

  5. Even thread prints even numbers from 0 to 1000 偶数线程打印从0到1000的偶数

  6. However they should be in sync the prints should be 1 , 2 , 3 , 4 ..... 但是,它们应该保持同步,打印件应为1,2,3,4 .....

  7. One number on each line 每行一个数字

However I can't seem to get the locks to release correctly. 但是我似乎无法正确释放锁。 I've tried reading some of the similar problems on here but they all use multiple classes. 我试过阅读一些类似的问题,但它们都使用多个类。 What am I doing wrong? 我究竟做错了什么?

Edit: My main class is doing this - 编辑:我的主要班级正在这样做-

NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");

oddPrinter.start();
evenPrinter.start();

and my output is - odd: 1 even: 2 ... 我的输出是-奇数:1偶数:2 ...

public class NumberPrinter extends Thread {

private String name;
private int starterInt;
private boolean toggle;


public NumberPrinter(String name) {
    super.setName(name);
    this.name=name;

    if(name.equals("odd")) {
        starterInt=1;
        toggle = true;

    }
    else if(name.equals("even")) {
        starterInt=2;
        toggle = false;
    }
}

@Override
public synchronized void run() {

    int localInt = starterInt;
    boolean localToggle = toggle;

    if(name.equals("odd")) {


    while(localInt<1000) {

        while(localToggle == false)
        try {
            wait();
        }catch(InterruptedException e) {

              System.out.println("Main thread Interrupted");

        }
    System.out.println(name+": "+localInt);
    localInt +=2;
    localToggle = false;
    notify();

       }
    }

    else {

        while(localInt<1000) {


            while(localToggle == true)
                try {
                    wait();
                }catch(InterruptedException e) {

                      System.out.println("Main thread Interrupted");

                }
            System.out.println(name+": "+localInt);
            localInt +=2;
            localToggle = true;
            notify();
    }
}
}
}

The key problem here is that the two threads have no way to coordinate with each other. 这里的关键问题是两个线程无法相互协调。 When you have a local variable ( localToggle in this case) nothing outside the method can observe or alter its value. 当您有一个局部变量(在这种情况下为localToggle )时,方法外的任何对象都无法观察或更改其值。

If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads. 但是,如果您与两个线程共享一个对象,则其状态可以更改,并且如果使用正确,则两个线程都可以看到这些状态更改。

You will see examples where the shared object is an AtomicInteger , but when you use synchronized , wait() and notify() , you don't need the extra concurrency overhead built into the atomic wrappers. 你会看到实例共享对象是AtomicInteger ,但是当你用synchronizedwait()notify()你不需要内置到原子包装的额外开销的并发性。

Here's a simple outline: 这是一个简单的轮廓:

class Main {
  public static main(String... args) {
    Main state = new Main();
    new Thread(new Counter(state, false)).start();
    new Thread(new Counter(state, true)).start();
  }
  int counter;
  private static class Counter implements Runnable {
    private final Main state;
    private final boolean even;
    Counter(Main state, boolean even) {
      this.state = state;
      this.even = even;
    }
    @Override
    public void run() {
      synchronized(state) {
        /* Here, use wait and notify to read and update state.counter 
         * appropriately according to the "even" flag.
         */
      }
    }
  }
}

I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. 我不清楚自己是否使用wait()notify()是分配的一部分,但此大纲的替代方法是使用BlockingQueue类的东西在两个线程之间来回传递令牌。 The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely. (容易出错的)状态监视将内置到队列中,从而清理代码并减少出错的可能性。

I finally got it working in a way that meets the standards required by my assignment. 我终于使它以符合我的作业要求的标准的方式工作。 Thank you all for your input. 谢谢大家的意见。 I'll leave the answer here for anyone who might need it. 我将答案留给可能需要的人。

public class Demo {

public static void main(String[] args) {

    NumberPrinter oddPrinter = new NumberPrinter("odd");
    NumberPrinter evenPrinter = new NumberPrinter("even");



    oddPrinter.start();
    evenPrinter.start();




    System.out.println("Calling thread Done");

} }

public class NumberPrinter extends Thread {

private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;



public NumberPrinter(String name) {

        this.name = name;

        if(name.equals("even")) {
            remainder=0;

        }else {
            remainder=1;


        }
    }

@Override
public void run() {



        while(startNumber<max) {
            synchronized(lock) {
                while(startNumber%2 !=remainder) {
                    try {
                    lock.wait();
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(name+": "+startNumber);
                startNumber++;
                lock.notifyAll();
            }
        }

}

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM