使用线程会扰乱我的暂停系统

Use of a thread messes up my pausing system

我的代码有问题。计时器总体上似乎工作正常,暂停按钮也能正常工作。

问题是当您在特定时间暂停时钟然后取消暂停时。

如果我们(比方说)在 8 秒暂停并在一分钟后取消暂停,它不会像 9-10-11 那样继续运行,等等。它会运行 74-75-76...(我把它分成分钟和秒)。

是线程导致的问题吗? (此外,我过度使用了 freeze_sec 和 freeze_min 时间代码片段,只是为了看看它是否会被修复,但事实并非如此。)

代码如下:

Thread t1 = null;

ss = new ServerSocket(6800);
while(true) {
    s = ss.accept();
    isr = new InputStreamReader(s.getInputStream());
    br = new BufferedReader(isr);
    message = br.readLine();

    if (message.equals("START")) {
        t1 = new Thread(new Thread1());
        t1.start();

        ...

    } else if (message.equals("PAUSE")) {
        if(check) {
            try {
                check = false;
                Thread1.PAUSE(true);
            } catch (Exception e) {
            System.out.println("Exception e");
        }
    } else {
        check = true;
        Thread1.PAUSE(false);
    }
}

Thread1 class 看起来像:

import java.io.*;
import java.util.Date;
import java.util.Scanner;

public class Thread1 extends MyServerFrame implements Runnable{

    private static int current_min_time = 0;
    private static int current_sec_time = 0;
    private static int freeze_min_time = 0;
    private static int freeze_sec_time = 0;
    private static boolean pause = false;
    private static int minutes = 0;
    private int total_time_sec = 0;
    private static boolean freeze_signal = false;
    private static int k = 0;

    @Override
    public void run() {

        long elapsedTime = 0L;

        boolean bool = true;
        int num = 0;

        while (bool) {
            Scanner scan = new Scanner(System.in);

            if (minutes == 0) {
                System.out.println("How many minutes for this half-time?");
                Scanner in = new Scanner(System.in);
                num = in.nextInt();
                minutes = num;
            }

            long startTime = System.currentTimeMillis();

            while (total_time_sec < minutes * 60 || freeze_signal == false) {

                if (freeze_signal && k == 0) {
                    freeze_sec_time = current_sec_time;
                    freeze_min_time = current_min_time;
                    k++;
                }

                if (!pause) {
                    //perform db poll/check
                    if (elapsedTime / 1000 != current_sec_time) {
                        try {
                            clearTheFile("Half_Time.txt");
                        } catch (IOException e) {
                            System.out.println("Exception");
                        }
                        if (!freeze_signal && k > 0) {
                            current_sec_time = freeze_sec_time;
                            current_min_time = freeze_min_time;
                            k = 0;
                        }
                        current_sec_time++;
                        total_time_sec = current_sec_time + current_min_time / 60;
                        print_in_txt();
                    }
                    elapsedTime = (new Date()).getTime() - startTime;

                    if (current_sec_time == 60) {
                        if (!freeze_signal && k > 0) {
                            current_sec_time = freeze_sec_time;
                            current_min_time = freeze_min_time;
                            try {
                                clearTheFile("Half_Time.txt");
                            } catch (IOException e) {
                                System.out.println("Exception");
                            }
                            print_in_txt();
                            k = 0;
                        }
                        current_sec_time = 0;
                        current_min_time++;
                        total_time_sec = current_sec_time + current_min_time / 60;
                        startTime = System.currentTimeMillis();
                        elapsedTime = (new Date()).getTime() - startTime;
                        try {
                            clearTheFile("Half_Time.txt");
                        } catch (IOException e) {
                            System.out.println("Exception");
                        }
                        print_in_txt();
                    }
                }
            }
        }
    }        

    public static void clearTheFile(String txt_name) throws IOException {
        try {
            FileWriter fwOb = new FileWriter(txt_name, false);
            PrintWriter pwOb = new PrintWriter(fwOb, false);
            pwOb.flush();
            pwOb.close();
            fwOb.close();
        } catch (IOException e) {}
    }

    public static void print_in_txt() {
        PrintWriter out;
        try {
            out = new PrintWriter("Half_Time.txt");
            out.println(String.format("%02d", current_min_time) + ":" + String.format("%02d", current_sec_time));
            out.print("");
            out.close();
        } catch (FileNotFoundException e) {
            System.err.println("File doesn't exist");
            e.printStackTrace();
        }

    }

    public static void PAUSE(boolean p) {
        if (p) {
            pause = true;
            freeze_signal = true;
        } else {
            current_sec_time = freeze_sec_time;
            current_min_time = freeze_min_time;
            try {
                clearTheFile("Half_Time.txt");
            } catch (IOException e) {
                System.out.println("Exception");
            }
            print_in_txt();
            pause = false;
            freeze_signal = false;
        }
    }
}   

所以,在花了一些时间思考这个想法之后,我突然意识到你实际上根本不需要线程。

您需要的是一种计算时间点之间持续时间的方法,它不需要线程来更新状态,它是自动完成的。

线程正在做"other stuff"

所以,基于此,我从我的 ...

中拿了一个 StopWatch class
public class StopWatch {

    private Instant startTime;
    private Duration totalRunTime = Duration.ZERO;

    public StopWatch start() {
        startTime = Instant.now();
        return this;
    }

    public StopWatch stop() {
        Duration runTime = Duration.between(startTime, Instant.now());
        totalRunTime = totalRunTime.plus(runTime);
        startTime = null;
        return this;
    }

    public StopWatch pause() {
        return stop();
    }

    public StopWatch resume() {
        return start();
    }

    public StopWatch reset() {
        stop();
        totalRunTime = Duration.ZERO;
        return this;
    }

    public boolean isRunning() {
        return startTime != null;
    }

    public Duration getDuration() {
        Duration currentDuration = Duration.ZERO;
        currentDuration = currentDuration.plus(totalRunTime);
        if (isRunning()) {
            Duration runTime = Duration.between(startTime, Instant.now());
            currentDuration = currentDuration.plus(runTime);
        }
        return currentDuration;
    }
}

并应用它可以在 Thread 内使用,这将简单地打印 运行 时间。

围绕这一点,我添加了暂停、恢复和停止线程的功能,以演示基本思想...

public class StopWatchRunnable implements Runnable {

    private final Lock pauseLock = new ReentrantLock();
    private final Condition pauseCondtion = pauseLock.newCondition();
    private final AtomicBoolean isPaused = new AtomicBoolean(false);
    private final AtomicBoolean isRunning = new AtomicBoolean(true);

    private final StopWatch stopWatch = new StopWatch();

    @Override
    public void run() {
        stopWatch.start();
        while (isRunning.get()) {
            while (isPaused.get()) {
                pauseLock.lock();
                stopWatch.pause();
                try {
                    pauseCondtion.await();
                } catch (InterruptedException ex) {
                } finally {
                    pauseLock.unlock();
                    stopWatch.resume();
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
            Duration duration = stopWatch.getDuration();
            String formatted = String.format("%dhrs %02dmins, %02dseconds", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart());
            System.out.println(formatted);
        }
    }

    public void stop() {
        pauseLock.lock();
        try {
            isPaused.set(false);
            isRunning.set(false);
        } finally {
            pauseCondtion.signalAll();
            pauseLock.unlock();
        }
    }

    public void pause() {
        pauseLock.lock();
        try {
            isPaused.set(true);
        } finally {
            pauseLock.unlock();
        }
    }

    public void resume() {
        pauseLock.lock();
        try {
            isPaused.set(false);
        } finally {
            pauseCondtion.signalAll();
            pauseLock.unlock();
        }
    }

}

可运行示例...

这基本上是从上面获取代码并将其转储到一个简单的可运行示例中,该示例演示了 pause/resume 功能

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class StopWatchExample {

    public static void main(String[] args) throws InterruptedException {
        new StopWatchExample();
    }

    public StopWatchExample() throws InterruptedException {
        StopWatchRunnable stopWatch = new StopWatchRunnable();
        Thread thread = new Thread(stopWatch);
        thread.start();

        Thread.sleep(5000);
        System.out.println("Pause...");
        stopWatch.pause();
        Thread.sleep(5000);
        System.out.println("Resume...");
        stopWatch.resume();
        Thread.sleep(5000);
        System.out.println("Stop...");
        stopWatch.stop();
        thread.join();
        System.out.println("All done...");
    }

    public class StopWatch {

        private Instant startTime;
        private Duration totalRunTime = Duration.ZERO;

        public StopWatch start() {
            startTime = Instant.now();
            return this;
        }

        public StopWatch stop() {
            Duration runTime = Duration.between(startTime, Instant.now());
            totalRunTime = totalRunTime.plus(runTime);
            startTime = null;
            return this;
        }

        public StopWatch pause() {
            return stop();
        }

        public StopWatch resume() {
            return start();
        }

        public StopWatch reset() {
            stop();
            totalRunTime = Duration.ZERO;
            return this;
        }

        public boolean isRunning() {
            return startTime != null;
        }

        public Duration getDuration() {
            Duration currentDuration = Duration.ZERO;
            currentDuration = currentDuration.plus(totalRunTime);
            if (isRunning()) {
                Duration runTime = Duration.between(startTime, Instant.now());
                currentDuration = currentDuration.plus(runTime);
            }
            return currentDuration;
        }
    }

    public class StopWatchRunnable implements Runnable {

        private final Lock pauseLock = new ReentrantLock();
        private final Condition pauseCondtion = pauseLock.newCondition();
        private final AtomicBoolean isPaused = new AtomicBoolean(false);
        private final AtomicBoolean isRunning = new AtomicBoolean(true);

        private final StopWatch stopWatch = new StopWatch();

        @Override
        public void run() {
            stopWatch.start();
            while (isRunning.get()) {
                while (isPaused.get()) {
                    pauseLock.lock();
                    stopWatch.pause();
                    try {
                        pauseCondtion.await();
                    } catch (InterruptedException ex) {
                    } finally {
                        pauseLock.unlock();
                        stopWatch.resume();
                    }
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                }
                Duration duration = stopWatch.getDuration();
                String formatted = String.format("%dhrs %02dmins, %02dseconds", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart());
                System.out.println(formatted);
            }
        }

        public void stop() {
            pauseLock.lock();
            try {
                isPaused.set(false);
                isRunning.set(false);
            } finally {
                pauseCondtion.signalAll();
                pauseLock.unlock();
            }
        }

        public void pause() {
            pauseLock.lock();
            try {
                isPaused.set(true);
            } finally {
                pauseLock.unlock();
            }
        }

        public void resume() {
            pauseLock.lock();
            try {
                isPaused.set(false);
            } finally {
                pauseCondtion.signalAll();
                pauseLock.unlock();
            }
        }

    }

}