how to restart a thread

心不动则不痛 提交于 2019-12-01 23:38:18

Instead of explaining, I just coded up a skeleton example. I did not test it terribly well, but it may be of some use.

In order to monitor a(nother) file, just create a new Monitor, passing it a ScheduledExecutorService. Starting and stopping monitoring is straightforward. You can (should) reuse the same executor for multiple monitors.

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();
    }

}

You don't restart a Thread, instead you create a new one each time you want to start a thread.

A better alternative may be to use Executors.newCachedThreadPool() which gives you a pool of thread which will be started/recycle for you.

BTW: You are using recursion rather than a loop to poll if the file exists. Using recursion can mean if you wait too long it will throw a StackOverflowError. IMHO you shouldn't wait at all, the polling thread should repeatedly attempt to open the file until it is told to stop (or the file appears)

Your current implementation also means if the file is replaced, you will have to reopen the file in the background thread anyway.

I assume you answered your question

one can not restart a dead thread

This link may be helpful to you How to restart thread in java?

A thread in Java cannot be re-started. Every time you need to restart the thread you must make a new one.

That said, you might want to look at:

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

Here you sleep for 30 seconds if the file does not exist, then recursively call the same function. Now, I don't know what business requirements you have, but if this recursion ran long enough you will run out of stack space. Perhaps you will be better served with a while loop or even better, a little synchronisation like a Semaphore.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!