java - 线程池任务列表更新问题

标签 java multithreading java-8 threadpool

关闭。这个问题需要details or clarity .它目前不接受答案。












想改进这个问题?通过 editing this post 添加详细信息并澄清问题.

2年前关闭。




Improve this question




我正在尝试在 java 中设计一个线程池。根据我的设计,我在主运行器线程类中使用 java 的 Linkedlist DS 来保留所有提交的任务。此任务列表正在从主类更新,其中主类正在将任务添加到任务列表。在我的主运行线程中,我正在运行一个 while 循环并不断检查 LinkedList 是否不为空,如果它包含一个任务,那么我正在检索该任务并执行它。

这里的问题是我已经从我的主方法中添加了一个任务到任务列表中,当我打印任务列表对象的大小时,我可以看到这个任务列表的大小是主方法中的 1,但是在运行器线程中,它显示为0。

需要帮助弄清楚这里到底发生了什么。

public class ReusableThread<T> extends Thread{
    private volatile Queue<Work<T>> tasks = new LinkedList<Work<T>>();
    private Work<T> currentWork;

    private class Work<T>{
        Result<T> result;
        Taskable<T> task;

        public Work(Result<T> result, Taskable<T> task) {
            this.result = result;
            this.task = task;
        }
    }

    @Override
    public void run() {
        while(true){
            //System.out.println("ReusableThread.run()");
            System.out.println("Inside thread : " + getTasks().size()); //This print 0
            if(!tasks.isEmpty()){      
               currentWork = getWork();
               T value = currentWork.task.run();

               //currentWork.result.setValue(currentWork.task.run());
            }
            //currentWork.result.setComplete(true);
        }
    }

    public Work<T> getWork() {
        return tasks.remove();
    }

    public Queue<Work<T>> getTasks() {
        return tasks;
    }

    public Result<T> submit(Taskable<T> task) {
        Result<T> result = new Result<T>();
        this.tasks.add(new Work<T>(result, task));
        return result;
    }
}

主线程如下:
public void test() throws InterruptedException {
    int count = 0;  
    ReusableThread<Integer> rt = new ReusableThread();
    rt.start();

    Thread.sleep(1000);

        System.out.println("Thread-"+ count +" starting");
        Result<Integer> result = rt.submit(JavaUtils::task);
        System.out.println("In main : " + rt.getTasks().size()); //This prints 1
}

最佳答案

我认为存在线程安全问题。具体来说:

  • 一个 LinkedList不是线程安全的,
  • 您正在使用 LinkedList rt.getTasks().size() 中的对象没有任何同步。

  • 这足以导致 size()在某些情况下返回一个陈旧的值。

    如果你要依赖 volatile 的语义您需要对对线程安全很重要的每个写入/读取序列的发生前关系进行适当的分析。这很棘手。

    我的建议是:
  • 不要使用 volatile .使用synchronized和/或现有的线程安全数据结构......如果您需要重新发明轮子。
  • 不要重新发明轮子。你可以用一个调用来替换你的线程池 Executors.singleThreadExecutor ;见 javadoc .
  • 关于java - 线程池任务列表更新问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59538846/

    相关文章:

    c - 如何获取 Win32 中的核心数?

    java - 为 Runnable 包装 Lambda 表达式以处理异常

    java - 在 Java 8 中的 Map<String, List> 中向 List 添加值

    java - 如何让 android 相机预览保持专注?

    java - typescript 编译(就Java编译而言)

    java try catch 并返回

    java - 如何在windows上远程调试tomcat 7.0?

    python - 下载大约 15000 个 URL 的元内容 Python - 线程

    java - 如何(全局)替换Java并行流的公共(public)线程池后端?

    java - 我如何从两个不同的抽象类中实现特定的方法?