使用ExecutorService保持计数器?

时间:2018-01-31 20:57:51

标签: java multithreading executorservice

我想保留一个执行线程的计数器,以便在我正在执行的相同线程中使用。

这里的问题是,虽然计数器增加,但它增加不均匀,并且从控制台输出我得到了这个(我有一个用ExecutorService执行5个线程的for循环):

This is a test. N:3
This is a test. N:4
This is a test. N:4
This is a test. N:4
This is a test. N:4

正如您所看到的那样,1,2,3,4,5没有获得3,4,4,4,4,而是for (int i = 0; i < 5; i++) { Thread thread; thread = new Thread() { public void run() { System.out.println("This is test. N: "+aldo ); //In here there is much more stuff, saying it because it might slow down the execution (if that is the culprit?) return; } }; threadList.add(thread); } //later for (int i = 0; i < threadList.size(); i++) { executor.execute(threadList.get(i)); aldo = aldo + 1; } executor.shutdown(); try { executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { }

我认为这是因为for循环运行得足够快以执行线程,并且线程足够快以执行请求计数器的代码比计数器可以更新自己更快(这是否有意义?)。

这是代码(它更小,对计数器没有意义用途):

aldo

是的,list.append代码中缺少计数器(我认为还有一些其他列表)(它们非常简单)。

2 个答案:

答案 0 :(得分:0)

WriteObject()不会被线程中的任务修改,而是在主线程中修改,在这里:

XmlWriterSettings

此外,由于您需要一个可以在多个线程中增加其值的计数器,因此您可以使用XmlWriter而不是aldo

您的代码应如下所示:

for (int i = 0; i < threadList.size(); i++) {
    executor.execute(threadList.get(i));
    //here...
    aldo = aldo + 1;
}

答案 1 :(得分:0)

我知道这样做的最好方法是创建一个带有传递数字的构造函数的自定义线程类。随后可以将保存该数字的变量用于任何所需的日志记录。这是我提出的代码。

public static void main(String[] args) {
    class NumberedThread implements Runnable {
        private final int number;
        public NumberedThread(int number) {
            this.number = number;
        }

        @Override
        public void run() {
            System.out.println("This is test. N: " + number);
        }
    }

    List<Thread> threadList = new ArrayList<>();
    for (int i = 1; i  <  6; i++) threadList.add(new Thread(new NumberedThread(i)));

    ExecutorService executor = Executors.newFixedThreadPool(10);;
    for (Thread thread : threadList) executor.execute(thread);
    executor.shutdown();
    try {
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    }
    catch (InterruptedException ignored) { }
}

如果您想命名线程,也可以使用字符串对象。