java - 在计时器中启动多个线程

标签 java multithreading timer

我来这里是为了回答问题,这让我忙了很长时间。

为了清楚起见,这就是我正在做的事情:

我正在创建一个java程序,它以图形的形式关注PLC中的数据。更具体地说,我正在使用 TimerTask 运行一个计时器,它会在每个周期从该 PLC 加载数据。但主要问题来了——从数据 block 读取单个变量大约需要 250ms。我想同时读取更多变量。所以基本上,它需要变量*250ms 的时间。 我认为这里的线程对于实现梦想的目标是绝对必要的。

更深入地了解代码:

从一开始。我正在启动一个计时器,如下所示:

Timer timer = new Timer();
timer.schedule(dc, 0, period);

其中 dc 是 DataCollector 类的实例,它从 PLC 获取数据。 DataCollector 中 run() 方法的一个重要片段如下所示:

@Override
public void run() {
    variables = readFromPlc();

这就是我现在面临的问题。 readFromPlc 从另一个称为 TCP 的类调用 read()。在该类中,我创建了与变量一样多的线程。但问题是如何让这些线程在一段时间内保持运行!我在构造函数中创建这些线程,并且在第一次,它们当然会调用 run() 并正确地从 plc 读取数据并将它们显示到图表中。但这是这些线程的结束 - run() 将不会再次被调用。

如果我可以反复停止和继续线程,那就太好了。但我是在这里被构造的。 PS:我不能简单地创建一个新的 TCP 实例,因为我有一些其他方法和功能代码,我不想再次运行。

或者非常简单: 我想每隔一段时间(例如每秒)运行线程的 run 方法。

如果有任何帮助,我将不胜感激。

谢谢,迈克尔

最佳答案

正如评论中提到的,关于如何使用 ExecutorService 来完成此操作的建议

编辑/注意:此示例仅显示基本方法。在实际应用程序中,您必须确保在不再需要 ExecutorService 时调用 shutdown()(或者允许核心线程超时)。

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ScheduledMultiThread
{
    public static void main(String[] args)
    {
        Timer timer = new Timer();
        long period = 1000;

        DataCollector dc = new DataCollector();
        timer.schedule(dc, 0, period);


    }
}

class DataCollector extends TimerTask
{
    private ExecutorService executorService;

    @Override
    public void run()
    {
        int variables = readFromPlc();
        if (executorService == null)
        {
            executorService = Executors.newFixedThreadPool(variables);
        }

        List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
        for (int i=0; i<variables; i++)
        {
            Runnable task = createTaskForVariable(i);
            tasks.add(Executors.callable(task));
        }
        try
        {
            executorService.invokeAll(tasks);
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
    }

    private Runnable createTaskForVariable(final int variable)
    {
        Runnable runnable = new Runnable()
        {
            @Override
            public void run()
            {
                executeTaskFor(variable);
            }
        };
        return runnable;
    }


    // Dummy implementations
    private void executeTaskFor(int variable)
    {
        System.out.println("Working for variable "+variable);
        try
        {
            Thread.sleep((long)(200+Math.random()*200));
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
        System.out.println("Working for variable "+variable+" DONE");
    }

    private int readFromPlc()
    {
        return 8;
    }


}

关于java - 在计时器中启动多个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21882285/

相关文章:

c++ - 如何用C连续输出计算开始后的秒数?

java - 处理中的多声道音频

java - 当前线程方法java

java - 是否可以将任何类型的输入传递给方法并确定给出的输入类型?

python - Python-启动线程会使用sys.exit()杀死所有线程

c# - 有界阻塞集合会在广告期间丢失数据吗

C++、mingw 和 clock_gettime 无法编译

c++ - 在 C++ 代码中指定的特定等待时间后执行某些操作?

java - 使用 java 解析多级 XML 文件(DOM 解析器)

java - java 程序中执行的函数列表(使用 eclipse)