【问题标题】:How do I make concurrently running threads?如何使并发运行的线程?
【发布时间】:2013-04-12 13:45:36
【问题描述】:

我想让两个单独的线程运行不同类的两个不同实例,并且我希望它们同时执行运行命令。

我开设了一个练习课来演示我遇到的问题。 一名赛车手向前数,另一名向后数。

public class testCount {

    public static void main(String args[]) {
        testCount countCompetition = new testCount();
        countCompetition.run();
    }

    public void run() {
        (new Thread(new racer1())).start();
        (new Thread(new racer2())).start();
    }

    public class racer1 implements Runnable {
        public void run() {
            for(int x = 0; x < 100; x++) {
                System.out.println(x);
            }
        }
    }
    public class racer2 implements Runnable {
        public void run() {
            for(int y = 100; y > 0; y--) {
                System.out.println(y);
            }
        }
    }
}

我的结果

1
2
... All the way to 100
100
100
99
... All the way back down
1

我想要什么

1
100
2
99
3
98

他们不需要像那样轮流工作,但他们确实需要同时工作,而不是一个接一个地工作。 任何提示、建议或代码 sn-ps 将不胜感激。

【问题讨论】:

    标签: java multithreading concurrency runnable


    【解决方案1】:

    我认为到目前为止所有的答案都没有抓住重点。

    您现有的逻辑确实使您的两个线程都可以同时执行,但这并不明显,因为您的数字最多只能达到 100,并且执行通常会一次在特定线程中停留超过 1 条指令,否则一直在当前正在执行的线程之间切换会产生大量开销。在您的情况下,JVM 决定执行您的第一个线程足够长的时间,以便在“上下文切换”到第二个线程之前打印出 100 个数字。 JVM 可能会选择以不同方式执行线程,因此不能保证每次看到的结果都相同。

    如果您将数字增加到 1000,您将(可能)看到两个线程有​​些交错。您仍然会有大量运行,其中一个线程连续打印出大量数字,因为 JVM 在切换之前执行一个线程一段时间,而不是在每条指令之间切换上下文更有效。

    添加 Thread.sleep(1) 不是一个好的解决方案,因为您添加了不必要的延迟。当然,对于 100 个号码,这可能并不明显,但对于 10000 个号码,您会有 10 秒的延迟。

    您是否有任何理由要求它们交错到比现在更高的程度?如果有那么您同时运行两个线程的简单模型是不够的。如果不是,那么只需让 JVM 决定运行线程的最佳顺序(在您给出的简单示例中,这意味着它们可能大部分时间都不会交错)。

    【讨论】:

    • 我不知道为什么您在此分析中被否决。用赞成票纠正它。
    【解决方案2】:

    只需在System.out.println() 之后的每个racer 类中添加Thread.sleep(1);

    即它看起来像这样:

    public class racer1 implements Runnable {
        public void run() {
            for(int x = 0; x < 100; x++) {
                System.out.println(x);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
    

    【讨论】:

    • @James 不让他们等待/睡眠的问题是第一个线程将在 100% 的时间内忙,因此第二个线程不会获得任何 CPU 时间。
    • 它也不保证线程会一个接一个地运行。你需要等待他们完成任务后互相通知
    • 感谢您的建议。幸运的是,线程交替对于我项目的这一部分来说并不是必不可少的。以后我会记住的。
    • 这不是关于交替线程,而是应该避免Thread.sleep()
    • @Andremoniy Thread.sleep 从来都不是避免竞争条件的方法,最糟糕的是,它会消耗更多的 CPU 用于......如果它唤醒并且条件(其他线程作业)不是尚未制作。在您的情况下,完全有可能产生意想不到的结果(导致无序)。管理您的案例的最佳方式之一:docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/…(比传统的基本 wait/notify 更好)
    【解决方案3】:

    您需要编写一个基本的等待和通知系统。一项任务需要通知另一项他已经完成了这项工作。基本思想可以从下面的代码中得出。创建 2 个任务,一个向前计数,一个向后计数

    Runnable task = new Runnable() {
      public void run() {
        System.out.println("woohooTwo");
        synchronized (t) {
          while (true) {
            System.out.println("---" + Thread.currentThread().getName() + "--" + t.i.getAndIncrement());
            t.notifyAll();
    
            try {
              Thread.sleep(1000);
              t.wait();
            } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
          }
    
        }
      }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 2017-05-31
      • 1970-01-01
      相关资源
      最近更新 更多