乐趣区

Java多线程练习交叉打印字符串

要求:使用两个线程交叉打印 n 次 ”foo” 和 ”bar”

1.FooBar 类

定义 foo 和 bar 的方法用来控制如何打印字符串。
foo 和 bar 方法接受一个 runnable 类,prinFoo, 和 printBar 为参数 该类用于在控制台输出一个字符串 ”foo” 或者 ”bar”。foo 和 bar 方法判断是否满足打印条件,并且执行 n 次。如果不满足条件,则暂时阻塞。

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 和 printFoo 类

定义一个 Runnable 类用于启动线程,打印字符串

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 类

用于测试

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();
        }
    }
}

备注:
Thread 类中 run() 和 start() 方法的区别如下:
run() 方法: 在本线程内调用该 Runnable 对象的 run() 方法,可以重复多次调用;
start() 方法: 启动一个线程,调用该 Runnable 对象的 run() 方法,不能多次启动一个线程

退出移动版