【问题标题】:How can I access the property value of a running Thread如何访问正在运行的线程的属性值
【发布时间】:2016-10-30 14:55:50
【问题描述】:

我有一个运行很长时间(5-6 分钟)的线程。

public class ExportThread implements Runnable {
    private Integer totalExport = 0;

    @Override
    public void run() {
        try {
            exportCorner();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void exportCorner() {
        List<MyObject> list = ......
        for(MyObject o : list){
            .......
            totalExport++;
        }
    }
}

此线程从另一个类运行。如何在一小段时间后一次又一次地获取 totalExport ?

【问题讨论】:

  • 我们通常如何获取private类字段的值呢?你在这里面临什么挑战?获取正确的值还是定期获取?从你的问题中你真的不清楚你尝试了什么以及你卡在哪里?

标签: java multithreading


【解决方案1】:

只需在线程类中添加一些 getter 即可获得它,正如@RomanKonoval 所说,它需要同步

public class ExportThread implements Runnable {
    private Integer totalExport = 0;

    @Override
    public void run() {
        try {
            exportCorner();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void exportCorner() {
        List<Integer> list = ......
        for(Integer i : list){
            totalExport += i;
        }
    }

    public synchronized Integer getTotalExport(){
        return this.totalExport;
    }
}

从你的其他班级你可以使用类似的东西

import java.util.*;

public class MainClass {
   public static void main(String[] args) {
       ExportThread exportThread = new ExportThread();
       Thread t = new Thread(exportThread); 
       t.start(); 

      TimerTask timerTask= new MyTimerTask(exportThread);
      Timer timer = new Timer();

      timer.scheduleAtFixedRate(tasknew,new Date(),1000);      
   }

}

那么你可能需要实现你的定时器任务

public class MyTimerTask extends TimerTask { 
    private ExportThread exportThread;
    public MyTimerTask(ExportThread exportThread){
        this.exportThread = exportThread;
    }
    @Override
    public void run() {
        System.out.println(exportThread.getTotalExports());
    }
}

【讨论】:

  • 我认为并发对于这种情况并不那么重要,因为您可以看到 totalExport 只是一个具有操作数量的状态属性
  • 如何从这里... public class ExecutorClass { public static void main(String[] args) { Thread t = new Thread(new ExportThread()); t.start(); } }
  • @elkorchianas 并发是这里的问题。您需要确保在一个线程中完成的更改在另一个线程中可见
  • @RomanKonoval 我明白你的意思,但这种情况需要定期获取 totalExport 值(如进度条)为什么我们需要进行同步?如果我们处理一些变量,它们的值控制应用程序的行为,您的建议可能很重要
  • JVM 可以优化对 totalExport 变量的访问,例如它可以将它存储在 CPU 寄存器中,更重要的是不要将更新的值保存到 RAM 中,这样其他线程会看到该变量的过时值。作为程序员,你有责任让 JVM 知道可以从其他线程访问此变量(这就是 volatile 存在的原因之一)。
【解决方案2】:

使用AtomicInteger的无锁解决方案

import java.util.*;
import java.util.concurrent.atomic.*;

public class ExportThread implements Runnable {
    private AtomicInteger totalExport = new AtomicInteger(0);

    @Override
    public void run() {
        try {
            exportCorner();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void exportCorner() {
        List<MyObject> list = new ArrayList<MyObject>(10);
        list.add(new MyObject());
        list.add(new MyObject());
        for(MyObject o : list){
            totalExport.getAndIncrement();
        }
        System.out.println("total export:"+getTotalExport());
    }
    public Integer getTotalExport(){
        return totalExport.get();
    }
    public static void main(String args[]){
        ExportThread t = new ExportThread();
        new Thread(t).start();
    }
}
class MyObject {

}

输出:

total export:2

步骤:

  1. 定义一个AtomicInteger
  2. 增加值
  3. 提供 get() 方法

相关的 SE 问题:

Practical uses for AtomicInteger

【讨论】:

    【解决方案3】:

    如果我正确理解了您的问题,它确实看起来像 观察者设计模式

    文档:https://en.wikipedia.org/wiki/Observer_pattern

    观察者模式是一种软件设计模式,其中一个对象, 称为主体,维护其依赖项的列表,称为 观察者,并自动通知他们任何状态变化, 通常通过调用他们的方法之一。它主要用于 实现分布式事件处理系统。观察者模式是 也是熟悉的模型-视图-控制器 (MVC) 中的关键部分 建筑模式。[1]观察者模式在 众多的编程库和系统,包括几乎所有的 GUI 工具包。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 1970-01-01
      相关资源
      最近更新 更多