JAVA简单线程,幻数问题(无法停止线程)

JAVA简单线程,幻数问题(无法停止线程),java,multithreading,android-studio,Java,Multithreading,Android Studio,我为android studio分配了这个任务,在那里我运行两个线程,都生成随机数,如果其中一个数字是幻数,它会停止两个线程,并在屏幕上显示幻数。我还不关心UI元素,所以不用担心,我只专注于尝试停止线程,因为我不能使用thread.stop,说实话,这看起来很简单,但在尝试了许多方法后,我不知道如何在找到一个神奇的数字后停止线程的运行,如果有人能告诉我它是怎么做的,我会更了解它。以下是完整的说明和代码: import android.os.Bundle; import android.util.

我为android studio分配了这个任务,在那里我运行两个线程,都生成随机数,如果其中一个数字是幻数,它会停止两个线程,并在屏幕上显示幻数。我还不关心UI元素,所以不用担心,我只专注于尝试停止线程,因为我不能使用thread.stop,说实话,这看起来很简单,但在尝试了许多方法后,我不知道如何在找到一个神奇的数字后停止线程的运行,如果有人能告诉我它是怎么做的,我会更了解它。以下是完整的说明和代码:

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Random;

/*
 1. The main activity creates and starts two threads using one Runnable object. Give each thread a name when it is created.
 The main activity controls the UI presentation. While waiting, it shows a ‘rotating’ progress bar.

2.  Each background thread does the following:
a.   sleep for 1 second,
b.  generate a random four-digit number,
c.  write the number and the thread’s name to the log,
d.   send a message containing the number to the main thread, then repeat the cycle.

3.  When the main activity receives a message containing a number, it determines if the number is ‘magic’. If it is ‘magic’,
it stops both background threads and displays the value of the magic number on the screen.  (Don’t use thread.stop() to stop the threads.)

A magic number is a four digit value that either (1) is a multiple of seven or (2) is a multiple of four and ‘2’ is its last digit.

4.  The first magic number written to the UI cannot be changed.
 */
public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MagicNumbers();
    }

    private static int limit = 100000;
    static int low = 1000;
    static int high = 9999;
    static String getThreadName;
    static String currentNumber;
    static Runnable create = new Runnable() {

        public void run() {
            for(int i = 0; i < MainActivity.limit; ++i) {
                try{
                    Thread.sleep(1000);   //makes threads sleep for 1 second
                }catch(InterruptedException e) {}
                getThreadName = Thread.currentThread().getName();   //gets the name of the current thread running
                Random r = new Random();                 //calculates random number
                int result = r.nextInt(high - low) + low;
                check_magic(result,getThreadName);
            }
        }
    };

    public static synchronized void check_magic(Integer value, String threadName) {
        if (value % 7 == 0 || value % 4 == 0 && value % 10 == 2) {
            currentNumber="MAGIC NUMBER GENERATED: "+value+", created by "+threadName;
            Log.i("Program2", currentNumber);
        }
        else {
            currentNumber="Number: "+value+", created by "+threadName;
            Log.i("Program2", currentNumber);
        }
    }

    public void MagicNumbers() {
        Thread thread1 = new Thread(create);
        Thread thread2 = new Thread(create);
        thread1.setName("ONE");
        thread2.setName("TWO");
        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException var7) {}
        
    }
}
导入android.os.Bundle;
导入android.util.Log;
导入androidx.appcompat.app.appcompat活动;
导入java.util.Random;
/*
1.主活动使用一个可运行对象创建并启动两个线程。在创建每个线程时为其指定一个名称。
主活动控制UI表示。等待时,它会显示一个“旋转”进度条。
2.每个后台线程执行以下操作:
A.睡1秒钟,
B生成一个随机的四位数,
C将编号和线程名称写入日志,
D将包含该编号的消息发送到主线程,然后重复该循环。
3.当主活动收到包含数字的消息时,它将确定该数字是否为“魔术”。如果是“魔法”,
它停止两个后台线程,并在屏幕上显示魔术数字的值。(不要使用thread.stop()停止线程。)
幻数是一个四位数的值,(1)是七的倍数,或者(2)是四的倍数,“2”是它的最后一个数字。
4.无法更改写入UI的第一个幻数。
*/
公共类MainActivity扩展了AppCompatActivity{
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MagicNumbers();
}
私有静态整数限制=100000;
静态int低=1000;
静态int高=9999;
静态字符串名;
静态字符串currentNumber;
静态Runnable create=new Runnable(){
公开募捐{
对于(int i=0;i
我只专注于尝试停止线程,因为我不能使用thread.stop,老实说,这似乎很简单,但在尝试了许多方法后,我不知道如何在找到一个神奇的数字后停止线程运行

有很多种方法可以在线程之间进行通信,这样它们就可以告诉对方它们已经找到了神奇的数字。最简单的方法是他们共享一个
volatile boolean found
字段。因此,
create
类将具有:

 private volatile boolean found;
在这个循环中:

// run until down or if the other thread finds the winning magic
for(int i = 0; i < MainActivity.limit && !found; ++i) {
因为该字段是易变的,所以两个线程都可以看到另一个线程的更新,并停止自己的循环

几点意见:

  • synchronized
    方法中的静态字段中存储内容不是一种好模式。
    即使一个线程发现了魔法,另一个线程也会覆盖静态字段。这可能是你问题的根源。我将创建一个实现
    Runnable
    FindMagicRunnable
    类。两个类都需要共享相同的
    found
    ,但它们应该有自己的
    currentNumber
    threadName
    实例字段
  • getThreadName
    是方法的名称,而不是字段。该字段为
    threadName
比如:

// both threads would set this, you could also use a shared AtomicBoolean
static volatile boolean found;
....
private static class FindMagicRunnable implements Runnable {
    String threadName;
    int winningMagic;
    ...
}

    FindMagicRunnable run1 = new FindMagicRunnable();
    FindMagicRunnable run2 = new FindMagicRunnable();
    Thread thread1 = new Thread(run1);
    Thread thread2 = new Thread(run2);
    thread1.setName("ONE");
    thread2.setName("TWO");
    thread1.start();
    thread2.start();

    try {
        thread1.join();
        thread2.join();
    } catch (InterruptedException var7) {}
    
    if (run1.winningMagic != 0) {
       // thread1 is the winner
    } else {
       // thread2 is the winner
    }

如果两个线程同时找到中奖号码,则此实现存在一些竞争条件。如果你想让它变得完美,那么你应该使用,并使用
testAndSet(…)
自动设置名称和中奖号码。

你可以使用
thread.interrupt()停止线程。
。但是,如果要这样做,则需要修复代码,使其不会捕获并忽略正在中断的线程中的
InterruptedException
。看起来你的代码中还有其他问题。。。根据要求。。。但是您可能还没有完全实现它们。我尝试过使用Thread.interrupt(),但仍然无法让程序停止线程,因为它不允许我在没有try and catch的情况下使用Thread.join()。其他要求是关于UI的,所以我不太担心。它应该可以工作。。。如果你做对了。请向我们展示您使用中断的(完整)尝试,以便我们可以看到什么
// both threads would set this, you could also use a shared AtomicBoolean
static volatile boolean found;
....
private static class FindMagicRunnable implements Runnable {
    String threadName;
    int winningMagic;
    ...
}

    FindMagicRunnable run1 = new FindMagicRunnable();
    FindMagicRunnable run2 = new FindMagicRunnable();
    Thread thread1 = new Thread(run1);
    Thread thread2 = new Thread(run2);
    thread1.setName("ONE");
    thread2.setName("TWO");
    thread1.start();
    thread2.start();

    try {
        thread1.join();
        thread2.join();
    } catch (InterruptedException var7) {}
    
    if (run1.winningMagic != 0) {
       // thread1 is the winner
    } else {
       // thread2 is the winner
    }