当前位置: 首页 > 面试题库 >

如何重新启动线程

东方琪
2023-03-14
问题内容

我试图编写一个文件监视器,它将检查文件是否添加了新行,该监视器实际上是一个线程,它将始终由randomaccessfile读取该行。

这是监视器的核心代码:

public class Monitor {
    public static Logger                                    log             = Logger.getLogger(Monitor.class);
    public static final Monitor             instance        = new Monitor();
    private static final ArrayList<Listener>    registers       = new ArrayList<Listener>();

    private Runnable                                        task            = new MonitorTask();
    private Thread                                          monitorThread   = new Thread(task);
    private boolean                                         beStart         = true;

    private static RandomAccessFile                         raf             = null;
    private File                                            monitoredFile   = null;
    private long                                            lastPos;

    public void register(File f, Listener listener) {
        this.monitoredFile = f;
        registers.add(listener);
        monitorThread.start();
    }

    public void replaceFile(File newFileToBeMonitored) {
        this.monitoredFile = newFileToBeMonitored;

        // here,how to restart the monitorThread?
    }

    private void setRandomFile() {
        if (!monitoredFile.exists()) {
            log.warn("File [" + monitoredFile.getAbsolutePath()
                    + "] not exist,will try again after 30 seconds");
            try {
                Thread.sleep(30 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setRandomFile();
            return;
        }
        try {
            if (raf != null) {
                raf.close();
                lastPos = 0;
            }
            raf = new RandomAccessFile(monitoredFile, "r");
            log.info("monitor file " + monitoredFile.getAbsolutePath());
        } catch (FileNotFoundException e) {
            // The file must exist now
        } catch (IOException e) {}
    }

    private void startRead() {
        beStart = true;
        String line;
        while (beStart) {
            try {
                raf.seek(lastPos);
                while ((line = raf.readLine()) != null) {
                    fireEvent(new FileEvent(monitoredFile.getAbsolutePath(),
                            line));
                }
                lastPos = raf.getFilePointer();
            } catch (IOException e1) {}
        }
    }

    private void stopRead() {
        this.beStart = false;
    }

    private void fireEvent(FileEvent event) {
        for (Listener lis : registers) {
            lis.lineAppended(event);
        }
    }

    private class MonitorTask implements Runnable {
        @Override
        public void run() {
            stopRead();

            //why putting the resetReandomAccessFile in this thread method is that it will sleep if the file not exist.
            setRandomFile();
            startRead();
        }

    }

}

这是一些帮助类:

public interface Listener {
    void lineAppended(FileEvent event);
}


public class FileEvent {
    private String  line;
    private String  source;

    public FileEvent(String filepath, String addedLine) {
        this.line = addedLine;
        this.source = filepath;
    }
    //getter and setter

}

这是调用监视器的示例

public class Client implements Listener {
    private static File f   = new File("D:/ab.txt");

    public static void main(String[] args) {
        Monitor.instance.register(f, new Client());
        System.out.println(" I am done in the main method");
        try {
            Thread.sleep(5000);
            Monitor.instance.replaceFile(new File("D:/new.txt"));
        } catch (InterruptedException e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void lineAppended(FileEvent event) {
        String line = event.getLine();
        if (line.length() <= 0)
            return;
        System.err.println("found in listener:" + line + ":" + line.length());
    }
}

现在,我的问题是,如果我仅调用以下代码,代码就可以很好地工作:

Monitor.instance.register(file,listener);

这将监视文件的行追加,并通知侦听器。

但是,当我致电:

Monitor.instance.replaceFile(anotherfile);

这意味着我想监视另一个文件而不是之前。

因此,在Monitor中,我必须重新启动线程,该怎么做?

我已经尝试过:

monitorThread.interruppt();

它不会扭曲。

任何人都可以为我修复它或告诉我该怎么做?

谢谢。

在我询问之前,我已经搜索了“重新启动Java线程”,因此我知道一个无法重新启动死线程,但是我的线程不返回,因此我认为可以重新启动它。


问题答案:

我没有解释,只是编写了一个框架示例。我没有对它进行很好的测试,但这可能有一定用处。

为了监视(另一个)文件,只需创建一个新的Monitor,并向其传递ScheduledExecutorService。启动和停止监视非常简单。您可以(应该)将同一个执行程序重用于多个监视器。

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public interface Event
{
}

public interface Listener
{
    void handle(Event event);
}

public class Monitor
{
    private static final int CHECK_EVERY_SECONDS = 10;
    private static final int RECHECK_AFTER_IF_NOT_EXISTS_SECONDS = 30;

    private File file;
    private ScheduledExecutorService executor;
    private boolean active;
    private List<Listener> listeners;

    public Monitor(File file, ScheduledExecutorService executor)
    {
        super();
        this.file = file;
        this.executor = executor;
        listeners = new ArrayList<Listener>();
    }

    public synchronized void start()
    {
        if (active)
        {
            return;
        }
        active = true;
        executor.execute(new Runnable()
        {
            public void run()
            {
                synchronized (Monitor.this)
                {
                    if (!active)
                    {
                        System.out.println("not active");
                        return;
                    }
                }
                if (!file.exists())
                {
                    System.out.println("does not exist, rescheduled");
                    executor.schedule(this, RECHECK_AFTER_IF_NOT_EXISTS_SECONDS, TimeUnit.SECONDS);
                    return;
                }
                Event event = doStuff(file);
                System.out.println("generated " + event);
                updateListeners(event);
                System.out.println("updated listeners and rescheduled");
                executor.schedule(this, CHECK_EVERY_SECONDS, TimeUnit.SECONDS);
            }
        });
    }

    private Event doStuff(final File file)
    {
        return new Event()
        {
            public String toString()
            {
                return "event for " + file;
            }
        };
    }

    public synchronized void stop()
    {
        active = false;
    }

    public void addListener(Listener listener)
    {
        synchronized (listeners)
        {
            listeners.add(listener);
        }
    }

    public void removeListener(Listener listener)
    {
        synchronized (listeners)
        {
            listeners.remove(listener);
        }
    }

    private void updateListeners(Event event)
    {
        synchronized (listeners)
        {
            for (Listener listener : listeners)
            {
                listener.handle(event);
            }
        }
    }

    public static void main(String[] args) throws IOException
    {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
        File file = new File("test.png");
        Monitor monitor = new Monitor(file, executor);
        monitor.addListener(new Listener()
        {
            public void handle(Event event)
            {
                System.out.println("handling " + event);
            }
        });
        monitor.start();
        System.out.println("started...");
        System.in.read();       
        monitor.stop();
        System.out.println("done");
        executor.shutdown();
    }

}


 类似资料:
  • 问题内容: 我很难找到一种方法来启动,停止和重新启动Java中的线程。 具体来说,我在中有一个类Task(当前实现)。我的主应用程序需要能够在线程上启动此任务,在需要时停止(杀死)该线程,有时还可以杀死并重新启动该线程… 我的第一次尝试是与,但我似乎找不到办法重新启动任务。当我使用任何将来的呼叫失败时,因为是“关机” … 那么,我该怎么做呢? 问题答案: 一旦线程停止,你将无法重新启动它。但是,没

  • 问题内容: 我编写了一个任务,通过套接字发送某些TCP消息。我有一个包含一堆消息和一些时间戳的文件,因此我将该任务编程为TimerTask,并使用带有第一个消息时间戳的Timer对其进行了调度。 完成后,任务运行方法结束,但其关联的线程仍然存在,不会被取消。如果我尝试使用新的时间重新安排任务,则会收到异常消息,通知我无法重新安排已安排的任务或取消的任务。 在重新计划之前,我也尝试过使用cancel

  • 问题内容: 您如何使python程序自动重新启动?因此,假设有一个非常简单的程序,例如: 现在,在Python Shell中,您将必须按“运行”按钮,然后按“运行模块(F5)”,或者仅按键盘上的“ f5”按钮。那是您第一次运行它。程序结束后,您将返回到“ Cheese.py”文件,然后按“ f5”再次运行该程序。大家和我在一起吗?好的,所以我的问题是,如何使程序自动重新启动,而无需手动执行? 问题

  • 问题内容: 如何重新启动Java AWT应用程序?我有一个附加了事件处理程序的按钮。我应该使用什么代码来重新启动应用程序? 我想做与应用程序中相同的事情。 问题答案: 当然,可以重新启动Java应用程序。 以下方法显示了一种重新启动Java应用程序的方法: 基本上,它执行以下操作: 查找Java可执行文件(我在这里使用了Java二进制文件,但这取决于您的要求) 查找应用程序(在我的情况下是一个ja

  • 问题内容: 我有一个静态课程(Foo)和一个主课程(Main) 参见Main.java: 参见Foo.java: 有什么方法可以重新启动或重置静态类? 注意:我需要这样做是因为我正在用jUnit测试静态类,并且需要在第二次测试之前清除参数。 编辑 几乎解决方案: 使用StanMax答案,我可以这样做: Main.java MyClassLoader.java Foo.java 输出值 问题:如果我

  • 我成功地使用了BenjaminRH的jQuery-ticker。它在提示字段提交后被激发,但是一旦ticker运行了一次并且需要再次被激发,它就不被激发了。 该报价器以以下方式启动 我试图用 没有成功。帮助是非常宝贵的。多谢了。