[英]Trying to stop a single thread out of multiple running at the same time in java
So im trying to stop a single thread when I have multiple threads running, here is the code im using to initialise the threads.所以当我有多个线程运行时,我试图停止单个线程,这是我用来初始化线程的代码。 Basically I have multiple textFields in javafx, and when a button is clicked on the screen, it fills the textFields, one by one, with an incrementing timer.
基本上我在 javafx 中有多个 textField,当在屏幕上单击一个按钮时,它会用递增的计时器一个一个地填充 textField。 Now I also have a button for each of the textfields to clear it, but the problem is when I clear it, because the thread is still running, the timer vanishes for a second and comes back because of the line 'orderTimes.get(boxNo).setText(minute + second);'
现在我还有一个用于每个文本字段的按钮来清除它,但问题是当我清除它时,因为线程仍在运行,计时器会消失一秒钟并由于行 'orderTimes.get(boxNo ).setText(分+秒);' in the code.
在代码中。
Now what I've tried is creating a list of threads and I've tried implementing it below but it doesn't work, this is so I can call each individual thread if its button to clear has been clicked.现在我尝试的是创建一个线程列表,我已经尝试在下面实现它,但它不起作用,这样我就可以在单击要清除的按钮时调用每个单独的线程。
Does anyone know how I can close/stop only one single thread out of multiple that are running?有谁知道我如何才能关闭/停止正在运行的多个线程中的一个? If more info is needed just let me know, thanks.
如果需要更多信息,请告诉我,谢谢。
public static void createIncrementingTimer(int boxNo, List<TextField> orderTimes) {
minutesList.set(boxNo, 0);
secondsList.set(boxNo, 0);
state = true;
new Thread(threadList.get(boxNo)) {
int currentMinutes = 0;
int currentSeconds = 0;
public void run() {
for (;;) {
if (state = true) {
try {
sleep(1000);
if (secondsList.get(boxNo) > 59) {
secondsList.set(boxNo, 0);
currentSeconds = 0;
minutesList.set(boxNo, currentMinutes + 1);
currentMinutes++;
}
if (secondsList.get(boxNo) < 10) {
second = ":0" + Integer.toString(secondsList.get(boxNo));
} else {
second = ":" + Integer.toString(secondsList.get(boxNo));
}
secondsList.set(boxNo, currentSeconds + 1);
currentSeconds++;
if (minutesList.get(boxNo) < 10) {
minute = "0" + Integer.toString(minutesList.get(boxNo));
} else {
minute = Integer.toString(minutesList.get(boxNo));
}
orderTimes.get(boxNo).setText(minute + second);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
threadList.get(boxNo).start();
}
The code I'm using to clear the textfields is below, with orderTimes being the list of textFields that I'm trying to clear.我用来清除文本字段的代码如下,orderTimes 是我要清除的文本字段列表。
public static void eraseBox(int clickedButtonNumber, List<TextArea> orderContentsList, List<TextField> tableNumbers, List<TextField> orderNumbers, List<TextField> orderTimes) {
orderContentsList.get(clickedButtonNumber).setText(null);
tableNumbers.get(clickedButtonNumber).clear();
orderNumbers.get(clickedButtonNumber).clear();
orderTimes.get(clickedButtonNumber).clear();
}
I would suggest you try to avoid Threads
.我建议你尽量避免
Threads
。 The Animation
API is designed to make doing work that would normally be done in a Thread
easier. Animation
API 旨在使通常在Thread
完成的工作变得更容易。 In this example, the IncrementingTimer
class consists of two Labels
and three Buttons
.在此示例中,
IncrementingTimer
类由两个Labels
和三个Buttons
。 The Labels
are used to show the time. Labels
用于显示时间。 The Buttons
are used to control the Timeline
. Buttons
用于控制Timeline
。 The Timeline
is used to increment the Labels
value each second or every sixty seconds. Timeline
用于每秒或每六十秒增加Labels
值。 I have added three IncrementingTimers
to the app.我在应用程序中添加了三个
IncrementingTimers
。
Main主要的
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
var scene = new Scene(new VBox(new IncrementingTimer(), new IncrementingTimer(), new IncrementingTimer()), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
IncrementingTimer递增定时器
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.util.Duration;
/**
*
* @author blj0011
*/
final public class IncrementingTimer extends HBox
{
IntegerProperty secondsCounter = new SimpleIntegerProperty();//Keeps up with seconds
IntegerProperty minutesCounter = new SimpleIntegerProperty();//Keeps up with minutes
Label lblSeconds = new Label();//Displays the seconds
Label lblMinutes = new Label();//Displays the minutes
Label lblColon = new Label(":");//Display the colon between minutes and seconds
Button btnPlay = new Button("Play");//Plays the Timeline
Button btnStop = new Button("Stop");//Stops the Timeline
Button btnPause = new Button("Pause");//Pauses the Timeline
Timeline timeline;//Used to run code that changes the Labels. This Timeline runs every one second.
public IncrementingTimer()
{
lblSeconds.textProperty().bind(secondsCounter.asString("%02d"));//Binds the seconds label to the seconds counter. Sets the String to always show two digits. Exmaple 1 is shown as 01.
lblMinutes.textProperty().bind(minutesCounter.asString("%02d"));//Binds the minutes label to the minutes counter. Sets the String to always show two digits. Exmaple 1 is shown as 01.
getChildren().addAll(lblMinutes, lblColon, lblSeconds, btnPlay, btnStop, btnPause);
timeline = new Timeline(new KeyFrame(Duration.seconds(1), (event) -> {//Replace the one with .016 to speed this up for testing purposes.
secondsCounter.set(secondsCounter.get() + 1);
if (secondsCounter.get() == 60) {
secondsCounter.set(0);
minutesCounter.set(minutesCounter.get() + 1);
if (minutesCounter.get() == 60) {
minutesCounter.set(0);
}
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
btnPlay.setOnAction((event) -> {
timeline.play();
});
btnPause.setOnAction((event) -> {
timeline.pause();
});
btnStop.setOnAction((event) -> {
timeline.stop();
secondsCounter.set(0);
minutesCounter.set(0);
});
this.setAlignment(Pos.CENTER);
}
}
As recommended and demonstrated by Sedric, use JavaFx Animation tools for the counters.按照 Sedric 的建议和演示,对计数器使用 JavaFx 动画工具。
The following one-file mre demonstrating implementation of counters using two different animation tools.以下单文件mre演示了使用两种不同动画工具实现计数器。
One uses PauseTransition
and uses Timeline
, each with its stop button.一种使用
PauseTransition
并使用Timeline
,每个都有其停止按钮。
(copy-paste the entire code into Timers.java
and run) (将整个代码复制粘贴到
Timers.java
并运行)
import java.io.IOException;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.PauseTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Timers extends Application {
@Override public void start(final Stage stage) throws IOException {
VBox root = new VBox(new CounterPane(new TimeLineCounter()), new CounterPane(new PauseTransitionCounter()));
stage.setScene(new Scene(root));
stage.show();
}
public static void main(final String[] args) { launch(args); }
}
class CounterPane extends HBox{
private final Counter counter;
CounterPane(Counter counter) {
super(5);
this.counter = counter; //todo: check not null
Button stopBtn = new Button("Stop");
stopBtn.setOnAction(e->stop());
getChildren().addAll(stopBtn, counter);
}
void stop(){
counter.getAnimation().stop();
}
}
abstract class Counter extends Label {
protected int count = 0;
public Counter() {
setAlignment(Pos.CENTER); setPrefSize(25, 25);
count();
}
abstract void count();
abstract Animation getAnimation();
}
class TimeLineCounter extends Counter {
private Timeline timeline;
@Override
void count() {
timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
final KeyFrame keyFrame = new KeyFrame(
Duration.seconds(1),
event -> { setText(String.valueOf(count++) ); }
);
timeline.getKeyFrames().add(keyFrame);
timeline.play();
}
@Override
Animation getAnimation() {
return timeline;
}
}
class PauseTransitionCounter extends Counter {
private PauseTransition pauseTransition;
@Override
void count() {
pauseTransition = new PauseTransition(Duration.seconds(1));
pauseTransition.setOnFinished(event ->{
setText(String.valueOf(count++) );
pauseTransition.play();
});
pauseTransition.play();
}
@Override
Animation getAnimation() {
return pauseTransition;
}
}
The if(state=true)
should rather be if(state==true)
or just if(state)
, but in fact the for(;;)
could do the entire thing as while(state)
, simply shutting down the thread when you set state=false
. if(state=true)
应该是if(state==true)
或只是if(state)
,但实际上for(;;)
可以像while(state)
一样完成整个事情,只需在以下情况下关闭线程你设置state=false
。
Then, fully stopping the thread could happen as state=false;threadList.get(boxNo).join();
然后,完全停止线程可能会发生
state=false;threadList.get(boxNo).join();
, and you can clear the field only after that (since the thread will set it to something in the last step too). ,并且您只能在此之后清除该字段(因为线程也会在最后一步将其设置为某些内容)。
With a simpler approach you could throw away the state
, and revert to for(;;)
, with the twist of having the try-catch()
around the loop, outside.使用更简单的方法,您可以丢弃
state
,并恢复到for(;;)
,并在循环外使用try-catch()
进行扭曲。 This way you can use threadList.get(boxNo).interrupt();threadList.get(boxNo);.join();
这样你就可以使用
threadList.get(boxNo).interrupt();threadList.get(boxNo);.join();
to stop the thread, and on top of that it will be immediate, as the sleep()
ends immediately when the thread is interrupted.停止线程,最重要的是它将是立即的,因为当线程被中断时
sleep()
立即结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.