简体   繁体   English

在计时器中启动多个线程

[英]Starting multiple threads in timer

I came here for an answer of question which keeps me busy for a longer time. 我来这里是为了回答问题,这使我忙了更长的时间。

For clarity, this is what I am doing: 为了清楚起见,这就是我在做什么:

I am creating a java program, which keeps an eye on datas in PLC in form of Graph. 我正在创建一个Java程序,它以Graph形式关注PLC中的数据。 Being more specific, I am running a single Timer with TimerTask, which keeps loading data from that PLC every period. 更具体地说,我使用TimerTask运行单个Timer,该计时器在每个周期都不断从该PLC加载数据。 But here comes the main problem - a single variable readed from data block takes about 250ms. 但这是主要问题-从数据块读取单个变量大约需要250毫秒。 I want to read more variables at the same time. 我想同时阅读更多变量。 So basically, it takes variables*250ms in time. 因此,基本上,这需要花费时间* 250ms。 I think that threading here would be absolutely necessary to achieve dreamed goals. 我认为在这里实现目标绝对是必要的。

Come little more deeper into the code: 深入了解代码:

From the beginning. 从一开始就。 I am starting a Timer as this: 我正在这样启动一个计时器:

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

Where the dc is instance of a DataCollector class, which gets the data from PLC. dc是DataCollector类的实例,该类从PLC获取数据。 A vital fragment of method run() in DataCollector is like this: DataCollector中方法run()的重要片段如下:

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

And here comes the problem I am standing at. 这就是我所面临的问题。 readFromPlc calls read() from another class called TCP. readFromPlc从另一个称为TCP的类调用read()。 In that class, I am creating as many threads as are variables. 在该类中,我创建的线程与变量一样多。 But the problem is how to keep those threads running in period of time!. 但是问题是如何使这些线程在一段时间内运行! I create those Threads in constructor and at the first time, they of course call run() and properly read datas from plc and show them to a graph. 我在构造函数中创建这些线程,并且在第一次时,它们当然会调用run()并从plc正确读取数据并将其显示为图形。 But that's end of those threads - run() won't be called again. 但这就是这些线程的结尾-不会再次调用run()。

If i could stop and continue threads repeatedly, that would be great. 如果我可以停止并继续重复执行线程,那就太好了。 But I am structed here. 但是我被安排在这里。 PS: I can't simple make a new instance of TCP, because I have some other methods and functional code there which I don't want to run again. PS:我不能简单地创建TCP的新实例,因为那里还有其他一些方法和功能代码,我不想再次运行。

OR very simplyfied: I want to run threads' run method every period of time (fe every second). 或者很简单:我想每隔一段时间(每秒一次)运行线程的运行方法。

I would appreciate any help. 我将不胜感激任何帮助。

Thanks, Michael 谢谢迈克尔

As mentioned in the comment, a suggestion about how this might possibly be done using an ExecutorService 正如在评论中提及,关于如何建议有可能会被使用做ExecutorService

EDIT/NOTE : This example only shows the basic approach. 编辑/注意 :此示例仅显示基本方法。 In the real application, you'd have to make sure that shutdown() is called on the ExecutorService once it is no longer required (or alternatively, allow the core threads to time out). 在实际的应用程序中,必须确保不再需要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;
    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM