Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何同时调用两个线程?_Java_Multithreading - Fatal编程技术网

Java 如何同时调用两个线程?

Java 如何同时调用两个线程?,java,multithreading,Java,Multithreading,我正在尝试编写线程干扰示例 下面是我的代码: class Counter { private int c = 0; public void increment() { c++; } public void decrement() { c--; } public int value() { return c; } } 假设线程A调用增量的时间与线程B调用减量的时间大致相同。 如何

我正在尝试编写线程干扰示例

下面是我的代码:

class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }    
}
假设线程A调用增量的时间与线程B调用减量的时间大致相同。
如何实现这一点

无法保证他们将如何运行它取决于操作系统调度程序。没有比这更好的了

Thread a = new ThreadA();
Thread b = new ThreadB();
a.start();
b.start();

要使两个线程同时开始执行,可以使用闩锁。(也就是说,两个线程可以在尽可能近的距离内执行。)但对于单个增量/减量,可能需要多次运行才能观察到干扰。对于可重复的实验,您可能希望并行调用增量/减量多次,并观察c的最终值

final Counter counter = new Counter()
final CountDownLatch latch = new CountDownLatch(1);
Thread thread1 = new Thread(new Runnable() {
public void run() {
  latch.await();
  for (int i = 0; i < 100; i++) {
    counter.increment();
  }
}}).start():
Thread thread2 = new Thread(new Runnable() {
public void run() {
  latch.await();
  for (int i = 0; i < 100; i++) {
    counter.decrement();
  }
}}).start():
Thread.sleep(10);//give thread 2 a timeslice to hit the await
latch.countDown();
System.out.println(counter.value()); //non-zero value indicates interference
最终计数器=新计数器()
最终倒计时闩锁=新倒计时闩锁(1);
Thread thread1=新线程(new Runnable(){
公开募捐{
satch.wait();
对于(int i=0;i<100;i++){
counter.increment();
}
}}).start():
Thread thread2=新线程(new Runnable(){
公开募捐{
satch.wait();
对于(int i=0;i<100;i++){
计数器。减量();
}
}}).start():
睡眠(10)//给线程2一个时间片来执行等待
倒计时();
System.out.println(counter.value())//非零值表示干扰

现在在本例中,如果您尝试执行,并且输出
false
显示干扰

工作原理:
Runnable
s保持线程本地计数,每次调用
increment()
decrement()
,该计数都会递增。因此,在执行一段时间后,如果我们尝试验证这些值

那么你可以说:

计数器值=调用增量()-调用减量()

但当您在执行结束时尝试验证时,会得到
false
。这表明实际计数器值与预期值不符

public static void main(String[] args) throws InterruptedException
{
        Counter c = new Counter();
        IncrementingRunnable incRunnable = new IncrementingRunnable(c);
        DecrementingRunnable decRunnable = new DecrementingRunnable(c);

        Thread tA = new Thread(incRunnable);
        Thread tB = new Thread(decRunnable);

        tA.start();tB.start();

        Thread.sleep(10000);
        stop = true;

        tA.join();
        tB.join();

        //verify value
        int actualCount = c.c;
        int expectedCount = incRunnable.count - decRunnable.count;
        System.out.println(actualCount == expectedCount);
}


 public static volatile boolean stop = false;

static class IncrementingRunnable implements Runnable{
      volatile int count = 0;
      private Counter counter;

      public IncrementingRunnable(Counter c) {
        this.counter = c;
      }
      @Override
      public void run() {
            while(!stop){
                counter.increment();
                count++;
            }
      }
}

static class DecrementingRunnable implements Runnable{
      volatile int count = 0;
      private Counter counter;

      public DecrementingRunnable(Counter c) {
        this.counter = c;
      }
      @Override
      public void run() {
          while(!stop){
            counter.decrement();
            count++;
        }
      }
}

现在尝试将
计数器中的原语
c
更改为
AtomicInteger
,然后再次查看输出。您会发现,现在输出是
true

这是您无法控制的,它取决于线程调度程序,它将首先获得机会,尽管有并发控制机制来序列化。两个线程如何,它们正在等待某个事件(例如,时间调度)?运行两个线程数次,直到你受到干扰。。祈祷吧,这可能会有帮助@ᴍ阿伦ᴍ为什么不在这些线程中循环?保存线程创建和启动时间。两个线程如何,它们正在等待某个事件(某个精确时间事件),然后同时执行某个操作?这两个线程将依次调用。多谢各位much@Andremoniy当他们再次醒来时,取决于操作系统,没有保证,假设有一个内核,它怎么能同时运行两个线程?@codegeek
这一个将一个接一个地调用
——同样不确定,如果假设您的CPU一次能够运行多个线程(对于新的CPU是这样的)然后,对于多个try中的某个执行实例,两个try可能同时执行。@codegeek a.start();b、 start();不能保证a将首先运行我已经解释了它是如何工作的。@Bohemian如果您验证我的答案,我将不胜感激。闩锁会比在两者上都调用start好得多吗?我不这么认为。它只是将同步点从线程外部移动到线程内部。也许这会好一点,但是调用闩锁的第一个线程可以立即调出,那么您的情况也不会好一点。有了线程,就没有时间保证了。我提供了一个类似的答案,但是随机调用。如果您能验证它,我将不胜感激。@Bohemian是的,这会有所不同,如果您使用闩锁,可靠地查看干扰所需的迭代次数要少得多。“没有保证”与“它通常在未加载的机器上实际工作”是不同的。