2016-02-25 46 views
0

嗨,大家好,我正在关注一个教程,我很好奇几件事情,我尝试应用从教程中获得的知识。使用执行器和同步CountDownLatch在不同的类

下面是一个亚军类

package Tutorial2; 

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class Runner { 

    public void runIt() { 

     CountDownLatch latch = new CountDownLatch (6); 
     ExecutorService executor = Executors.newFixedThreadPool(2); 

     for (int i = 0; i < 10; i++) { 
      executor.submit(new Process(i, latch)); 
     } 

     ExecutorService executor2 = Executors.newFixedThreadPool(2); 

     for (int i = 1000; i < 1010; i++) { 
      executor2.submit(new Process(i, latch)); 
     } 

     try { 
      latch.await(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println("Program Ended"); 
    } 
} 

然后下面是我的处理器类

package Tutorial2; 

import java.util.concurrent.CountDownLatch; 

public class Process implements Runnable { 

    private int id; 
    CountDownLatch latch = new CountDownLatch(6); 

    public Process(int id, CountDownLatch latch) { 
     this.id = id; 
     this.latch = latch; 
    } 

    @Override 
    public void run() { 
     System.out.println("Task Starting ID : " + id); 

     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println("Task Finished ID : " + id); 
     latch.countDown(); 
    } 
} 

这是很简单的什么,我试图做的。所以我想问你一些专业人士的问题。所以我明白,每当调用.countDown时CountDownLatch都会减1。然后,如果倒计时为零,则等待将返回。

我很好奇的是Runner类中的CountDownLatch和Process类中的CountDownLatch应该不同,但在Process类的CountDownLatch中达到零也似乎触发了我在Runner类中放置的.await。当我只将CountDownLatch作为参数传递给Process类并且Process类中的CountDownLatch值没有返回给Runner类时,这是如何工作的?

另外,下面我设置了两个执行程序,这样每个执行程序都会对CountDownLatch进行倒计时,但是在返回之前,我似乎正在处理的线程数比我输入的数字(6)多。我究竟做错了什么?我如何做到这一点,以便当CountDownLatch达到0时即打印“程序结束”,即从两个执行程序中总共运行了6次线程。

回答

2

通过this.latch = latch;覆盖对象的引用与在构造函数参数中传递的引用(即在runIt方法中创建的引用)。在Process类中的作业CountDownLatch latch = new CountDownLatch(6);是无用的,它什么都不做。只是迷惑你。

第二个问题还不清楚......是的,只要它倒数到零,它就会发布await ......不知道它与你拥有多少线程/执行程序有关。

+0

那么Runner类中的CountDownLatch仍然在Process类中使用?因为我想如果一个值传递给另一个类的参数,它只会覆盖'value',但仍然在其方法中使用同一个类中的变量。 – forJ

+0

是啊不要担心第二个我认识到,如果我设置锁定为静态,那么它的工作 – forJ

+0

@forJ Java变量只保留对象的引用。你在'runIt'和Process类的两个地方创建对象,但你用前者覆盖对后者的引用。单词“overrides the'value'”在Java – kan

2

我在一个类中取得int countDown而在另一个类所做的一样int countDown。在一门课程中,我做了一个构造函数,通过countDown从另一个课程,我做了this.countDown = countDown,以确保它们引用相同的变量。然后我......但来自两个班的countDown并不指向相同的值。

变量不是Java中的其他任何东西都可以“引用”的东西。变量是一个指定位置,可以保存

Java中的所有值都可以分为两类: 对象编号原始值。对象引用是指向Java堆上的对象的指针。原始值基本上只是一个数字,如55int类型的原始值。


当你的程序执行this.countDown = countDown,这并不建立两个变量之间的关系。它所做的全部设置this.countDown等于该特定时刻countDown中发生的任何值。如果程序随后更改this.countDowncountDown,则对其他变量没有影响。

在一些编程语言,你可以创建一个别名 ---看起来像一个独特的可变的事情,但是这实际上是一些其他变量的引用---但你永远无法做到这一点的Java的。

+0

好吧,这有助于我的理解。所以它不会因为原始值而改变,因为它们只是指向数字,但在锁定指向对象之上的情况下,每次更改它的引用时都会改变它? – forJ

+1

@forJ,是的。类型为“CountDownLatch”的变量拥有对堆中对象的引用。两个不同的'CountDownLatch'变量都可以引用同一个对象。更改其中一个变量(例如,引用_different_'CountDownLatch'实例)不会影响其他变量,但这不是您的代码正在执行的操作。您的代码使用公共共享实例在线程之间进行通信。当您将变量的类型更改为“int”时,则不会有共享实例,因为“int”值不是堆中的对象。 –

+0

所以,即使我引用了一个对象,如果我已经锁定了该方法,整个类都包含在内,那么latch的值是不会改变的?它只是因为它在方法中的一个局部变量? – forJ