Java multi-threaded practice-cross print strings

Posted May 26, 20202 min read

Requirements:Use two threads to print "foo" and "bar" n times

1.FooBar class

The methods defining foo and bar are used to control how to print strings.
The foo and bar methods accept a runnable class, prinFoo, and printBar as parameters. This class is used to output a string "foo" or "bar" in the console. The foo and bar methods determine whether the printing conditions are met and execute n times. If the condition is not met, it is temporarily blocked.

package ThreadLeetcode;

class FooBar {
    private int n;
    private volatile boolean finish = false;
    public FooBar(int n) {
        this.n = n;
    }

    public void foo(Runnable printFoo) throws InterruptedException {

        for(int i = 0; i <n; i ++) {

            //printFoo.run() outputs "foo". Do not change or remove this line.
            while(finish) {
                Thread.yield();
            }
            printFoo.run();
            finish = true;
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {

        for(int i = 0; i <n; i ++) {

            //printBar.run() outputs "bar". Do not change or remove this line.
            while(! finish) {
                Thread.yield();
            }
            printBar.run();
            finish = false;
        }
    }
}

2.printBar and printFoo classes

Define a Runnable class to start the thread and print the string

package ThreadLeetcode;

public class PrintBar implements Runnable {
    @Override
    public void run() {
        System.out.printf("Bar \ n");
    }
}



package ThreadLeetcode;

public class PrintFoo implements Runnable {
    @Override
    public void run() {
        System.out.printf("Foo \ n");
    }
}

3.fooBarTest class

For testing

package ThreadLeetcode;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class FooBarTest {
    private ThreadPoolExecutor executor;

    public static void main(String []args) throws InterruptedException {
        //Init executor
        ThreadPoolExecutor executor;
        executor =(ThreadPoolExecutor) Executors.newFixedThreadPool(2);

        //init Task
        FooBar fooBar = new FooBar(4);
        FooTast fooTast = new FooTast(fooBar);
        BarTast barTast = new BarTast(fooBar);

        //Submit Task
        executor.submit(fooTast);
        executor.submit(barTast);

        //End Task
        while(executor.getActiveCount()> 0) {
            Thread.sleep(50);
        }
        executor.shutdown();
    }
}

class FooTast implements Runnable {
    PrintFoo printFoo = new PrintFoo();
    FooBar fooBar;

    public FooTast(FooBar foobar) {
        this.fooBar = foobar;
    }

    @Override
    public void run() {
        try {
            fooBar.foo(printFoo);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class BarTast implements Runnable {
    PrintBar printBar = new PrintBar();
    FooBar fooBar;

    public BarTast(FooBar foobar) {
        this.fooBar = foobar;
    }

    @Override
    public void run() {
        try {
            fooBar.bar(printBar);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Remarks:
The difference between the run() and start() methods in the Thread class is as follows:
run() method:call the run() method of the Runnable object in this thread, which can be called multiple times;
start() method:start a thread, call the run() method of the Runnable object, you cannot start a thread multiple times