【问题标题】:Java synchronizing with thread using getState methodJava使用getState方法与线程同步
【发布时间】:2021-02-08 18:09:07
【问题描述】:

我有两个班级:

  • TestClass,一个通过 Scanner 使用用户输入的类
class TestClass {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        System.out.print("1: ");
        String one = scan.nextLine();

        System.out.print("2: ");
        String two = scan.nextLine();

        System.out.print("3: ");
        String three = scan.nextLine();
    }
}
  • Test,向 TestClass 提供虚假输入以对其进行测试的类
public class Test {
    public static void main(String[] args) throws IOException {
        PipedOutputStream inputSimulator = new PipedOutputStream();
        PrintStream inputProvider = new PrintStream(inputSimulator);
        System.setIn(new BufferedInputStream(new PipedInputStream(inputSimulator)));

        Thread thread = new Thread(() -> TestClass.main(new String[]{}));
        thread.start();

        while (thread.getState() != Thread.State.TIMED_WAITING) ;
        inputProvider.println("One given");
        System.out.println("One given");

        while (thread.getState() != Thread.State.TIMED_WAITING) ;
        inputProvider.println("Two given");
        System.out.println("Two given");

        while (thread.getState() != Thread.State.TIMED_WAITING) ;
        inputProvider.println("Three given");
        System.out.println("Three given");
    }
}

我无法让 Test 类与 TestClass 同步。通过同步,我的意思是如果我想在控制台中打印它:

1: One given
2: Two given
3: Three given

但是,我得到:

1: One given
Two given
Three given
2: 3:

我使用while 循环来检查线程的扫描器当前是否正在等待输入。但是,在第一次输入之后,这种检查机制就不起作用了。我需要在不编辑 TestClass 的情况下执行此操作。有什么方法可以做到这一点?

【问题讨论】:

    标签: java multithreading parallel-processing synchronization java-threads


    【解决方案1】:

    通常依靠线程计时是一个非常糟糕的主意,但是根据您的 cmets 和约束,我能想到的最好方法是使用 Thread.sleep,如下所示:

        public static void main(String[] args) throws IOException, InterruptedException {
            PipedOutputStream inputSimulator = new PipedOutputStream();
            PrintStream inputProvider = new PrintStream(inputSimulator);
            System.setIn(new BufferedInputStream(new PipedInputStream(inputSimulator)));
    
            Thread thread = new Thread(() -> TestClass.main(new String[]{}));
            thread.start();
    
            Thread.sleep(1000);
            while (thread.getState() != Thread.State.TIMED_WAITING) ;
            inputProvider.println("One given");
            System.out.println("One given");
    
            Thread.sleep(1000);
            while (thread.getState() != Thread.State.TIMED_WAITING) ;
            inputProvider.println("Two given");
            System.out.println("Two given");
    
            Thread.sleep(1000);
            while (thread.getState() != Thread.State.TIMED_WAITING) ;
            inputProvider.println("Three given");
            System.out.println("Three given");
        }
    }
    

    可能,对于您的上下文,您将不得不添加额外的检查等等。

    【讨论】:

    • PipedInputStream 读取的线程完全进入TIMED_WAITING 状态(而不是,例如WAITING),这看起来也像是一个未记录的实现细节。
    • 是的,这显然是生产中的不,但由于无法修改 TestClass 的限制,我没有看到不同的解决方法
    • 好吧,您可以将PipedOutputStream/PipedInputStream 组合替换为支持查询已经读取了多少先前写入的数据(甚至支持等待它)的东西。事实上,只需将一个非常小的缓冲区大小传递给PipedInputStream​ 的构造函数,就会产生每个inputProvider.println(…) 等待接收者的效果。如果这就是 OP 想要的,那么就不需要更多了。当然,此时不应该使用矛盾的BufferedInputStream
    • @Holger 感谢您的建议,我会照顾好工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    相关资源
    最近更新 更多