Альтернативная печать строк в двух потоках - PullRequest
0 голосов
/ 11 июля 2020

У меня есть этот код, где я хочу, чтобы оба напечатали foo и bar альтернативно n количество раз. Для этого случая я взял n как 1.

Этот код печатает foo дополнительно, еще раз.

Видно, что foo thread находится в режиме ожидания, и когда bar уведомляет, он запускается, но в идеале я хочу, чтобы foo и bar печатались только один раз.

Ниже код

Основной класс

public class TestClass {

    public static void main(String[] args) throws InterruptedException {

        FooBar foobar = new FooBar(1);
        new Thread(() -> {
            try {
                foobar.foo(new Runnable() {

                    @Override
                    public void run() {
                        System.out.println("foo");

                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                foobar.bar(new Runnable() {

                    @Override
                    public void run() {
                        System.out.println("bar");
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

    }

}

Общий объект

class FooBar {
    private int n;
    private boolean flag = true;
    private int i = 0;

    public FooBar(int n) {
        this.n = 2 * n;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        synchronized (this) {
            while (i < n) {
                System.out.println("Checking loop in foo " + i);
                while (!flag) {
                    System.out.println("foo waiting " + i);
                    this.wait();
                    System.out.println("foo notified " + i);
                }
                System.out.println("foo " + i);
                ++i;
                flag = !flag;
                notify();
            }
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        synchronized (this) {
            while (i < n) {
                System.out.println("checking loop in bar" + i);
                while (flag) {
                    System.out.println("bar waiting" + i);
                    this.wait();
                    System.out.println("bar notified" + i);
                }
                System.out.println("bar " + i);
                ++i;
                flag = !flag;
                notify();
            }
        }
    }
}

Как сделать нить foo , чтобы не печатать foo дважды ??

1 Ответ

0 голосов
/ 13 июля 2020

Вы можете попробовать это решение:

import java.util.concurrent.atomic.AtomicInteger;

public class TestClass {
    private int n;
    Object lock = new Object();
    AtomicInteger printFooNum = new AtomicInteger(1);
    AtomicInteger printBarNum = new AtomicInteger(1);

    public TestClass(int n) {
        this.n = n;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            synchronized (lock) {
            while(printFooNum.get()==0) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // printFoo.run() outputs "foo". Do not change or remove this line.
            printFoo.run();
            printFooNum.set(0);
            printBarNum.set(1);
            lock.notifyAll();
        }
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            synchronized (lock) {
                
            
            while(printBarNum.get()==0) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // printFoo.run() outputs "foo". Do not change or remove this line.
            printBar.run();
            printBarNum.set(0);
            printFooNum.set(1);
            lock.notifyAll();
        }
        }
    }
    public static void main(String[] args) throws InterruptedException{
        
        
        TestClass foobar = new TestClass(5);
        new Thread(() -> {
            try {
                foobar.foo(new Runnable() {

                    @Override
                    public void run() {
                        System.out.println("foo");

                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                foobar.bar(new Runnable() {

                    @Override
                    public void run() {
                        System.out.println("bar");
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...