线程不会在我想要的时候停止? (JAVA)

我的屏幕录制应用程序中有一个线程不合作:

package recorder; import java.awt.AWTException; import java.awt.Insets; import java.io.IOException; import javax.swing.JFrame; public class RepeatThread extends Thread { volatile boolean stop; public volatile Thread recordingThread; JFrame frame; int count = 0; RepeatThread( JFrame myFrame ) { stop = false; frame = myFrame; } public void run() { while( stop == false ) { int loopDelay = 33; // 33 is approx. 1000/30, or 30 fps long loopStartTime = System.currentTimeMillis(); Insets insets = frame.getInsets(); // Get the shape we're recording try { ScreenRecorder.capture( frame.getX() + insets.left, frame.getY() + insets.top, frame.getWidth() - ( insets.left + insets.right ), frame.getHeight() - ( insets.top + insets.bottom ) ); } catch( AWTException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } catch( IOException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } // Add another picture long loopEndTime = System.currentTimeMillis(); int loopTime = (int )( loopEndTime - loopStartTime ); if( loopTime < loopDelay ) { try { sleep( loopDelay - loopTime ); // If we have extra time, // sleep } catch( Exception e ) { } // If something interrupts it, I don't give a crap; just // ignore it } } } public void endThread() { stop = true; count = 0; ScreenRecorder.reset(); // Once I get this annoying thread to work, I have to make the pictures // into a video here! } } 

它已经困扰了我多年。 它会定期将截图截取到指定区域。

当您开始录制时,它会隐藏(取消激活)窗口。 在Mac上,当您提供应用程序焦点时,任何隐藏的窗口都将激活。 在我的class级WListener (我已确认工作),我有:

     public void windowActivated(WindowEvent e){
         if(ScreenRecorder.recordingThread!= null){
             ScreenRecorder.recordingThread.endThread();
         }
     }

所以应该发生的是,截屏模式在他点击应用程序时停止。 但是,我必须粗暴地搞砸了一些东西,因为当线程运行时,它甚至不会让窗口重新出现。 这是我的第一个post,所以我期待这样一个奇怪的问题。 你知道什么是错的吗?

编辑:好的,我停止了挥动,这里是我创建线程的地方:

 package recorder; import java.awt.AWTException; import java.awt.Robot; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.*; import javax.imageio.ImageIO; import javax.swing.JFrame; public class ScreenRecorder { static RepeatThread recordingThread; static int count; public static void record(JFrame frame) { if(recordingThread == null) { //Make a new thread if we don't have one recordingThread = new RepeatThread(frame); recordingThread.start(); } } public static void capture(int x, int y, int width, int height) throws AWTException, IOException { // capture the whole screen //BufferedImage screencapture = new Robot().createScreenCapture( // new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) ); BufferedImage screencapture = new Robot().createScreenCapture( new Rectangle( x, y, width, height)); // Save as JPEG File directory = new File("/Users/stuart/Movies/temp"); if(directory.exists() == false) { directory.mkdirs(); } count ++; File file = new File("/Users/stuart/Movies/temp/screencapture" + count + ".jpg"); ImageIO.write(screencapture, "jpg", file); // Save as PNG // File file = new File("screencapture.png"); // ImageIO.write(screencapture, "png", file); } public static void stop() { } public static void reset() { count = 0; } } 

由于您显然每隔X毫秒尝试执行一个工作单元,因此如果您使用Java的Executors,这将会容易得多:

 ScheduledExecutorService service = executors.newSingleThreadScheduledExecutor(); service.scheduleAtFixedRate(new Runnable() { public void run() { // do one iteration of your work ScreenRecorder.capture(...); ... } }, 0L, 33L, TimeUnit.MILLISECONDS); ... service.shutdown(); // to stop 

使用Thread手动执行此操作并不像您所做的那样混乱(不是嘲笑你,只是说它在Java中并不那么糟糕),但上述仍然是迄今为止最简单的选择。

您需要使stop停止,以便线程可以从另一个线程中获取更改。

这将修复1个错误,但还有一些其他线程相关的错误。 您应该阅读Java Concurrency in Practice。 在处理线程时,您需要使用volatilesynchronized