值在Runnable类中被覆盖 - Java

时间:2017-10-06 14:06:53

标签: java multithreading executorservice

我遇到Runnable类的问题。传递给runnable类的值将被相同值传递给另一个类时收到的最后一个值覆盖。 runnable类的功能是将值传递给另一个类中的另一个函数来打印它们。但只打印Runnable类收到的最后一个值。

这是我的代码, 这是传递值的主要类。

-F

这是我用来调用线程的executorUtil。

public class MainClass {
    private int intVal = -1;
    public void MainMethod() {
        ExecutorUtil theExecutor = ExecutorUtil.GetInstance();
        for(int i = 0; i < 3; i++) {
            intVal = i;
            synchronized (this) {
                theExecutor.SubmitTask(new ActionExecutor(intVal));
            }
        }
    }
}

这是将接收到的值传递给打印这些值的函数的线程。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.BlockingQueue;

public class ExecutorUtil {
    private static ExecutorUtil theInstance;
    private ExecutorService theExecutor;
    private BlockingQueue<Runnable> theQueue;



    protected ExecutorUtil() {
        theExecutor = CreateThreadPoolExecutor();
    }

    private ExecutorService CreateThreadPoolExecutor() {
        theQueue = new LinkedBlockingQueue<Runnable>();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 900, java.util.concurrent.TimeUnit.SECONDS, theQueue);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        return threadPoolExecutor;
    }

    public static ExecutorUtil GetInstance() {
        if (theInstance == null) {
            synchronized(ExecutorUtil.class) {
                if (theInstance == null) {
                    theInstance = new ExecutorUtil();
                }
            }
        }
        return theInstance;
    }

    public void SubmitTask(Runnable runnable) {
        theExecutor.submit(runnable);
    }
}

这是打印值的类。

public class ActionExecutor implements Runnable {
    int iVal = -1;
    public ActionExecutor(int iVal) {
        this.iVal = iVal;
    }
    public void run() {
        SecondClass sc = new SecondClass();
        sc.printIntVal(iVal);
    }
}

预期产出:

public class SecondClass {
    public void printIntVal(int i) {
        System.out.println(i);
    }
}

获得输出:

0
1
2

不知道为什么这样做会这样!

更新

仅在使用非原始数据类型时才会出现此问题。在我的例子中,我使用了一个整数值(intVal)。由于java传递了原始数据类型的值,因此按预期获得了输出。但在我的原始代码中,我使用了JSONObject。由于java为非原始数据类型传递了对象的引用,因此该值被覆盖。

我通过为每次迭代创建新的JSONObject来解决这个问题。

2 个答案:

答案 0 :(得分:0)

似乎某个地方有静态字段,用于存储您的号码。 所以,我想,你有3个ActionExecutor实例,但看起来field有静态修饰符,所以每个实例都有最新的值。

检查此案例......

答案 1 :(得分:0)

所以在我阅读你的问题并研究你的代码后,我不妨试一试。并且看到它按预期工作。这里唯一的区别是存在竞争条件,因此输出我的顺序不同,但它不会打印相同的数字。 输出可能

  • 1st:0 1 2
  • 第二名:0 1 2
  • 第3名:2 1 0

以下是试用它的完整代码:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

public class MainClass {

     private int intVal = -1;
        public void MainMethod() {
            ExecutorUtil theExecutor = ExecutorUtil.GetInstance();
            for(int i = 0; i < 3; i++) {
                intVal = i;
                synchronized (this) {
                    theExecutor.SubmitTask(new ActionExecutor(intVal));
                }
            }
        }

        public class ActionExecutor implements Runnable {
            int iVal = -1;
            public ActionExecutor(int iVal) {
                this.iVal = iVal;
            }
            public void run() {
                SecondClass sc = new SecondClass();
                sc.printIntVal(iVal);
            }
        }
        public class SecondClass {
            public void printIntVal(int i) {
                System.out.println(i);
            }
        }

        public static class ExecutorUtil {
          private static ExecutorUtil theInstance;
            private ExecutorService theExecutor;
            private BlockingQueue<Runnable> theQueue;



            protected ExecutorUtil() {
                theExecutor = CreateThreadPoolExecutor();
            }

            private ExecutorService CreateThreadPoolExecutor() {
                theQueue = new LinkedBlockingQueue<Runnable>();
                ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 900, java.util.concurrent.TimeUnit.SECONDS, theQueue);
                threadPoolExecutor.allowCoreThreadTimeOut(true);
                return threadPoolExecutor;
            }

            public static ExecutorUtil GetInstance() {
                if (theInstance == null) {
                    synchronized(ExecutorUtil.class) {
                        if (theInstance == null) {
                            theInstance = new ExecutorUtil();
                        }
                    }
                }
                return theInstance;
            }

            public void SubmitTask(Runnable runnable) {
                theExecutor.submit(runnable);
            }
        }

        public static void main(String[] args) {
            MainClass main = new MainClass();
            main.MainMethod();
        }
}

您可能希望清理并重建项目。否则它正在工作..