Java 如何重新启动线程

Java 如何重新启动线程,java,multithreading,restart,Java,Multithreading,Restart,我试着写一个文件监视器,如果添加了新行,它将检查文件,监视器实际上是一个线程,它将一直通过随机访问文件读取该行 这是监视器的核心代码: public class Monitor { public static Logger log = Logger.getLogger(Monitor.class); public static final Monitor inst

我试着写一个文件监视器,如果添加了新行,它将检查文件,监视器实际上是一个线程,它将一直通过随机访问文件读取该行

这是监视器的核心代码:

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 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.replaceFile(anotherfile);
这意味着我想监视另一个文件,而不是以前

因此,在我的监视器中,我必须重新启动线程,如何使它

我已经试过了:

monitorThread.interruppt();
它不合适

谁能帮我修一下或者告诉我怎么做

谢谢


在我提问之前,我已经在谷歌上搜索了“重启java线程”,所以我知道不能重启一个死线程,但我的线程不会返回,所以我认为它可以重新启动。

请看这篇文章。

您不重启线程,而是在每次启动线程时创建一个新线程

更好的选择可能是使用Executors.newCachedThreadPool(),它为您提供了一个线程池,将为您启动/回收

顺便说一句:您正在使用递归而不是循环来轮询文件是否存在。使用递归可能意味着如果您等待太长时间,它将抛出StackOverflower错误。如果您根本不应该等待,轮询线程应该反复尝试打开文件,直到它被告知停止(或文件出现)


您当前的实现还意味着,如果文件被替换,您将不得不在后台线程中重新打开该文件。

我想您已经回答了您的问题

不能重新启动死线程


此链接可能对您有所帮助

Java中的线程无法重新启动。每次需要重新启动线程时,必须创建一个新线程

也就是说,您可能想看看:

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;
        }
// ....
}

在这里,如果文件不存在,则休眠30秒,然后递归调用相同的函数。现在,我不知道您有什么业务需求,但是如果这个递归运行足够长的时间,您将耗尽堆栈空间。也许使用while循环会更好,或者甚至更好,比如一个小的同步。

我没有解释,而是编写了一个框架示例。我没有很好地测试它,但它可能有一些用处

为了监视另一个文件,只需创建一个新的监视器,并向其传递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.io.File;
导入java.io.IOException;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.Executors;
导入java.util.concurrent.ScheduledExecutorService;
导入java.util.concurrent.TimeUnit;
公共接口事件
{
}
公共接口侦听器
{
无效句柄(事件);
}
公共班长
{
私有静态最终整数检查每秒钟=10;
如果不存在,则在\u之后重新检查\u私有静态最终整数\u秒=30;
私有文件;
专用ScheduledExecutorService执行器;
私有布尔活动;
私人名单听众;
公共监视器(文件、ScheduledExecutorService执行器)
{
超级();
this.file=文件;
this.executor=执行人;
侦听器=新的ArrayList();
}
公共同步的void start()
{
如果(活动)
{
返回;
}
主动=真;
executor.execute(新的Runnable()
{
公开募捐
{
已同步(Monitor.this)
{
如果(!活动)
{
System.out.println(“未激活”);
返回;
}
}
如果(!file.exists())
{
System.out.println(“不存在,重新安排”);
执行者计划(如果不存在,则在之后重新检查,时间单位为秒);
返回;
}
事件=doStuff(文件);
System.out.println(“生成的”+事件);
更新侦听器(事件);
System.out.println(“更新的侦听器并重新安排”);
执行者计划(此,每秒钟检查一次,时间单位为秒);
}
});
}
私有事件doStuff(最终文件)
{
返回新事件()
{
公共字符串toString()
{
返回“事件为”+文件;
}
};
}
公共同步无效停止()
{
主动=假;
}
公共void addListener(侦听器侦听器)
{
已同步(侦听器)
{
添加(侦听器);
}
}
公共void RemovelListener(侦听器侦听器)
{
已同步(侦听器)
{
删除(侦听器);
}
}
私有void更新侦听器(事件)
{
已同步(侦听器)
{
for(侦听器:侦听器)
{
句柄(事件);
}
}
}
公共静态void main(字符串[]args)引发IOException
{
ScheduledExecutorService executor=Executors.newScheduledThreadPool(4);
File File=新文件(“test.png”);
监视器=新监视器(文件、执行器);
monitor.addListener(新侦听器()
{
公共无效句柄(事件)
{
System.out.println(“处理”+事件);
}
});
monitor.start();
System.out.println(“已启动…”);
System.in.read();
monitor.stop();
系统输出打印项次(“完成”);
executor.shutdown();
}
}

实际上你说的正是我想要的。但是我现在不知道如何使用executeService,应该在
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;
        }
// ....
}
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();
    }

}