【问题标题】:Why do you need timeout in milliseconds and Why do I have to declare 2 Classes with separate run () methods for separate blocks为什么你需要以毫秒为单位的超时,为什么我必须为单独的块声明 2 个具有单独 run () 方法的类
【发布时间】:2020-05-31 05:22:30
【问题描述】:

我在理解我的多线程应用程序中发生的一些背景事情时遇到了问题。

我的问题 1:

我有一个类(称为 SyncClass),它负责在 2 个实例方法中创建同步块,称为 test1()test2()时间>。 test1() 应该将一个整数增加 1,然后将其打印出来,而 test2() 应该做同样的事情。只要值小于 10,这些方法就应该递增整数。所以基本上当 test1() 将值递增 1 时,它应该将其交给另一个方法 test2() 在满足条件之前应该做同样的事情。

目前这些 2 方法有等待(2000),因为如果我有一个没有限制的简单等待,那么程序只会继续执行,只有部分结果打印到屏幕上,然后它只是挂起。

可能必须有一个更好的等待来解决它而不需要超时,或者?

我的问题 2:

我有一个外部类(称为TheRunner)和另一个成员类(称为InnerRunner),它们都实现了Runnable,外部类具有run() 方法运行 test1() 方法和内部类运行 test2() 方法。

有没有办法让我只有一个实现 Runnable 的类在其中运行 test1() 和 test2() 方法(即在 run() 方法中)?

SyncClass 的代码如下所示:

package test;

public class SyncClass {

    int i = 0;
    boolean b = true;

    public void test1() {
        synchronized (this) {
            while((b == true) && (i < 10)) {
                i++;
                System.out.println("test 1:");
                System.out.println(i);
                b = false;

                try {
                    wait(2000);

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

            }
        }

    }



    public void test2() {
        synchronized (this) {
            while((b == false) && (i < 10)) {
                i++;
                System.out.println("test 2:");
                System.out.println(i);
                b = true;

                try {
                    wait(2000);
                    notify();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }


            }
        }
    }


}

然后我有另一个实现 Runnable 的类来运行上述方法:

package test;

public class TheRunner implements Runnable {

    SyncClass sync;

    public TheRunner(SyncClass sync) {
        this.sync = sync;
    }


    @Override
    public void run() {
        sync.test1();

    }



class InnerRunner implements Runnable{


    SyncClass sync;

    public InnerRunner(SyncClass sync) {
        this.sync = sync;
    }


    @Override
    public void run() {
        sync.test2();
    }


}   


    public static void main(String[] args) {


        SyncClass sync = new SyncClass();
        TheRunner runner = new TheRunner(sync);
        TheRunner.InnerRunner innerRunner = runner.new InnerRunner(sync);

        Thread t1 = new Thread(runner);
        Thread t2 = new Thread(innerRunner);
        t1.start();
        t2.start();



    }
}

如果我删除 wait(2000) 并用简单的 wait() 替换它,那么输出将只有:

测试1:
1

测试2:
2

..但它应该持续到 10,即下一次迭代应该是 test1: 3、test2: 4 等,当我用 wait(2000) 更改它时它会这样做。我真的不明白这个?

【问题讨论】:

  • 拜托,每个帖子一个问题。
  • 我考虑过发表一篇文章,因为它们相互关联。

标签: java multithreading runnable synchronized


【解决方案1】:

这是很多代码,有很多误解。我已经简化了这个例子,它不需要超时或将值传递给wait。您应该在实际代码中使用AtomicInteger,但在这里我使用了int[],因此您可以希望了解发生了什么。每当您wait 时,您需要确保调用某种形式的notify。让我们从 single Runnable 我命名为 Counter 开始。喜欢,

public class Counter implements Runnable {
    private static int[] ai = { 0 };
    private int threadId;

    public Counter(int threadId) {
        this.threadId = threadId;
    }

    @Override
    public void run() {
        synchronized (ai) {
            int v;
            while ((v = ai[0]) < 10) {
                if (v % 2 != threadId % 2) {
                    System.out.printf("%s test%d %d%n", 
                            Thread.currentThread().getName(), 
                            threadId, ai[0]++);
                    ai.notifyAll();
                } else {
                    System.out.printf("%s test%d wait%n", 
                            Thread.currentThread().getName(), threadId);
                    try {
                        ai.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

然后我们可以测试它(join(s) 不是绝对必要的,但我喜欢等待代码完成)就像

public static void main(String[] args) {
    Thread t1 = new Thread(new Counter(1));
    Thread t2 = new Thread(new Counter(2));
    t1.start();
    t2.start();
    try {
        t1.join();
        t2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

应该(始终)导致

Thread-0 test1 0
Thread-0 test1 wait
Thread-1 test2 1
Thread-1 test2 wait
Thread-0 test1 2
Thread-0 test1 wait
Thread-1 test2 3
Thread-1 test2 wait
Thread-0 test1 4
Thread-0 test1 wait
Thread-1 test2 5
Thread-1 test2 wait
Thread-0 test1 6
Thread-0 test1 wait
Thread-1 test2 7
Thread-1 test2 wait
Thread-0 test1 8
Thread-0 test1 wait
Thread-1 test2 9

【讨论】:

  • 您能否向我解释一下为什么我的代码可以在传递到 wait() 的超时值的情况下工作? ..IE。打印所有元素而不是没有超时?
  • 因为没有任何东西通知他们,他们一直等到超时到期。就这么简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 2023-03-15
相关资源
最近更新 更多