让线程从主线程等待
Making a thread wait from main thread
我已经阅读了很多关于让线程等待的消息,但我无法使任何事情正常进行。我已经阅读了有关等待、通知、加入、锁定的文档......但仍然找不到解决我问题的方法。
我有我的主流和另一个流在后台(用户不与之交互,它只是做他自己的事情)。然后在主流中,用户将有可能使用某些功能,直到他退出程序。我想要的是,当用户选择使用一个功能时,后台流在这个功能期间暂停,然后再开始。
我将在此处用 "pseudo" 代码进行解释:
main(args[]){
new Thread(new Background(), "Background").start();
while (user don't quit){
//user choose a function
-> find a way to pause Background thread
chosenFunction();
-> find a way to unpause the Background thread
}
}
public class Background implements Runnable{
public Background(){}
public void run(){
while (thread is not paused){
//do some stuff
}
}
}
我认为我不应该使用连接,因为我不想等待另一个线程完成,而是等待另一个线程中的函数完成。我认为锁定是答案,但我无法让它工作。我试过了:
main(args[]){
ReentrantLock lock = new ReentrantLock();
new Thread(new Background(lock), "Background").start();
while (user don't quit){
//user choose a function
lock.lock();
chosenFunction();
lock.unlock();
}
}
public class Background implements Runnable{
private final ReentrantLock lock;
public Background(ReentrantLock lock){
this.lock = lock;
}
public void run(){
while (!lock.islocked()){
//do some stuff
}
}
}
或者:
public void run(){
while(lock.isLocked){
sychronized(this){
wait();
}
}
//do some stuff
}
但是不行。
如果您需要更多上下文:后台线程正在等待来自套接字的消息,用户可以调用的函数也在使用这个套接字。所以是的,我的第一个想法是将这个套接字作为两个流之间的同步对象,但我也没有设法让它工作。
在你的第一个例子中:
new Thread(new Background(), "Background").start();
while (user don't quit){
//user choose a function
-> find a way to pause Background thread
chosenFunction();
-> find a way to unpause the Background thread
}
第一个问题是:为了了解其他对象,您需要某种句柄。你这里没有的。
含义:您的代码创建了一个新线程,并启动了它。但是对该线程的 reference 被丢弃了。除非您 保留 对它们的引用,否则您无法识别对象。您的 Background
对象也是如此。
换句话说:当你想让多个线程相互通信时,那么你就需要一个通信通道来连接这两者。例如:两个 线程实现都可以访问的对象。
赞(此处为伪代码):
Queue<String> commands = ...
new EnhancedThread(commands).start();
以上将启动一个新线程,并且该线程可以 "listen" 在 commands
队列中用于命令。所以你的主线程可以做:
commands.add("COMMAND1");
commands.add("SUSPEND");
等等。
重复:仅仅创建一个线程对象什么都不做。你必须考虑一个可以用来完成事情的 协议 。因此:关注这里的 design 方面。将您的线程视为人类。现在问问自己,要让这些人进行这种互动,你需要具体说明什么。
您当前的实施归结为 "talking to a random guy on the street, to then walk away from him." 但是您如何期望在您走开后随机的人会对您做出反应?你没有要他的 phone 号码,所以你打算怎么给他发信息?
您可以使用 volatile
变量。这是 volatile
变量的一个非常典型的用例。
public void main() {
BackgroundServiceThread bst = new BackgroundServiceThread();
bst.start();
while (true) {
//user choose a function
bst.isPaused = true;
chosenFunction();
bst.isPaused = false;
}
}
private static class BackgroundServiceThread extends Thread {
volatile boolean isPaused = false;
@Override
public void run() {
while (true) {
if (!isPaused) {
//do stuffs;
}
}
}
}
private void chosenFunction() {
//user choose function
}
当您在主线程中更新 isPaused 时,更改会立即在您的后台服务线程中可见,因为它是易变的。
我已经阅读了很多关于让线程等待的消息,但我无法使任何事情正常进行。我已经阅读了有关等待、通知、加入、锁定的文档......但仍然找不到解决我问题的方法。
我有我的主流和另一个流在后台(用户不与之交互,它只是做他自己的事情)。然后在主流中,用户将有可能使用某些功能,直到他退出程序。我想要的是,当用户选择使用一个功能时,后台流在这个功能期间暂停,然后再开始。
我将在此处用 "pseudo" 代码进行解释:
main(args[]){
new Thread(new Background(), "Background").start();
while (user don't quit){
//user choose a function
-> find a way to pause Background thread
chosenFunction();
-> find a way to unpause the Background thread
}
}
public class Background implements Runnable{
public Background(){}
public void run(){
while (thread is not paused){
//do some stuff
}
}
}
我认为我不应该使用连接,因为我不想等待另一个线程完成,而是等待另一个线程中的函数完成。我认为锁定是答案,但我无法让它工作。我试过了:
main(args[]){
ReentrantLock lock = new ReentrantLock();
new Thread(new Background(lock), "Background").start();
while (user don't quit){
//user choose a function
lock.lock();
chosenFunction();
lock.unlock();
}
}
public class Background implements Runnable{
private final ReentrantLock lock;
public Background(ReentrantLock lock){
this.lock = lock;
}
public void run(){
while (!lock.islocked()){
//do some stuff
}
}
}
或者:
public void run(){
while(lock.isLocked){
sychronized(this){
wait();
}
}
//do some stuff
}
但是不行。
如果您需要更多上下文:后台线程正在等待来自套接字的消息,用户可以调用的函数也在使用这个套接字。所以是的,我的第一个想法是将这个套接字作为两个流之间的同步对象,但我也没有设法让它工作。
在你的第一个例子中:
new Thread(new Background(), "Background").start();
while (user don't quit){
//user choose a function
-> find a way to pause Background thread
chosenFunction();
-> find a way to unpause the Background thread
}
第一个问题是:为了了解其他对象,您需要某种句柄。你这里没有的。
含义:您的代码创建了一个新线程,并启动了它。但是对该线程的 reference 被丢弃了。除非您 保留 对它们的引用,否则您无法识别对象。您的 Background
对象也是如此。
换句话说:当你想让多个线程相互通信时,那么你就需要一个通信通道来连接这两者。例如:两个 线程实现都可以访问的对象。
赞(此处为伪代码):
Queue<String> commands = ...
new EnhancedThread(commands).start();
以上将启动一个新线程,并且该线程可以 "listen" 在 commands
队列中用于命令。所以你的主线程可以做:
commands.add("COMMAND1");
commands.add("SUSPEND");
等等。
重复:仅仅创建一个线程对象什么都不做。你必须考虑一个可以用来完成事情的 协议 。因此:关注这里的 design 方面。将您的线程视为人类。现在问问自己,要让这些人进行这种互动,你需要具体说明什么。
您当前的实施归结为 "talking to a random guy on the street, to then walk away from him." 但是您如何期望在您走开后随机的人会对您做出反应?你没有要他的 phone 号码,所以你打算怎么给他发信息?
您可以使用 volatile
变量。这是 volatile
变量的一个非常典型的用例。
public void main() {
BackgroundServiceThread bst = new BackgroundServiceThread();
bst.start();
while (true) {
//user choose a function
bst.isPaused = true;
chosenFunction();
bst.isPaused = false;
}
}
private static class BackgroundServiceThread extends Thread {
volatile boolean isPaused = false;
@Override
public void run() {
while (true) {
if (!isPaused) {
//do stuffs;
}
}
}
}
private void chosenFunction() {
//user choose function
}
当您在主线程中更新 isPaused 时,更改会立即在您的后台服务线程中可见,因为它是易变的。