Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程:帮助我理解自己的stop()-方法(将布尔值设置为中断/终止线程)_Java_Multithreading_Interrupt - Fatal编程技术网

Java 线程:帮助我理解自己的stop()-方法(将布尔值设置为中断/终止线程)

Java 线程:帮助我理解自己的stop()-方法(将布尔值设置为中断/终止线程),java,multithreading,interrupt,Java,Multithreading,Interrupt,有很多问题问的基本相同,但使用建议的解决方案会给我带来一个问题 问题:如果使用布尔值确定是否允许我的线程继续运行,while循环检查是否调用了stop方法,因此,如果设置了中断变量,则将程序流保持在while循环中。 因此,我的线程(在后台运行)的实际用途丢失了 class MyThread implements Runnable { private String name; private long seconds; private boolean exitThread

有很多问题问的基本相同,但使用建议的解决方案会给我带来一个问题

问题:如果使用布尔值确定是否允许我的线程继续运行,while循环检查是否调用了stop方法,因此,如果设置了中断变量,则将程序流保持在while循环中。 因此,我的线程(在后台运行)的实际用途丢失了

class MyThread implements Runnable
{
    private String name;
    private long seconds;
    private boolean exitThread = false;

    MyThread(String name, long seconds)
    {
        this.name = name;
        this.seconds = seconds;
    }
    public void run()
    {
        while (!exitThread) 
        {
            try 
            {
                Thread.sleep(seconds* 1000);
                System.out.println("Thread \"" + name+ "\" started...");
                return;
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }

    public void stop()
    {
        this.exitThread = true;
    }
}
while-loop-in方法run阻止程序执行,直到线程完成/终止,而不是像我的线程那样在后台运行

后续问题:为什么我要在布尔变量上使用关键字volatile,因为我希望我创建的单个线程能够作为单个线程停止,而不是在一个正在运行的线程上将布尔变量设置为true时停止所有线程

编辑:线程的实例化:

    public void initThreads()
    {
        MyTimerThread newThread = new MyTimerThread("Thread1, 10);
        newThread.run();
        threadList.add(newThread);
        MyTimerThread newThread = new MyTimerThread("Thread2, 30);
        newThread.run();
        threadList.add(newThread);
    }

您必须用continue替换退货。Return结束while循环,从而结束您自己的线程实现

class MyThread implements Runnable
{
    private String name;
    private long seconds;
    private boolean exitThread = false;

    MyThread(String name, long seconds)
    {
        this.name = name;
        this.seconds = seconds;
    }
    public void run()
    {
        while (!exitThread) 
        {
            try 
            {
                Thread.sleep(seconds* 1000);
                System.out.println("Thread \"" + name+ "\" started...");
                continue;
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }

    public void stop()
    {
        this.exitThread = true;
    }
}
因为continue是方法中的最后一条语句,所以您也可以删除它

后续问题:关键字volatile表示变量在多个线程上使用,不应缓存在一个特定线程上

关于这个问题的投票答案进一步详细解释了这一点:

编辑: 下面是我为回答您在这个答案上留下的注释而做的一个示例:

class MyThread implements Runnable
{
    private String name;
    private long seconds;
    private volatile boolean exitThread = false;

    private int count;

    MyThread(String name, long seconds)
    {
        this.name = name;
        this.seconds = seconds;
    }

    public void run()
    {
        while (!this.exitThread)
        {
            try
            {
                if(!Thread.currentThread().isInterrupted())
                {
                    Thread.sleep(this.seconds * 1000);
                    System.out.println("Runnable '" + this.name + "' run() " + this.count);
                    this.count++;
                }
                continue;
            }
            catch (InterruptedException e)
            {
                System.out.println("Runnable '" + this.name + "' ended.");
            }
        }
    }

    public void stop()
    {
        this.exitThread = true;
    }
}
您可以像这样使用:

MyThread runnable = new MyThread("Task 1", 1);
Thread threadA = new Thread(runnable);
threadA.start();

try 
{
    System.out.println("Sleeping Main Thread.");
    Thread.sleep(4 * 1000);
    System.out.println("Main Thread Continued.");
}
catch (Exception e)
{
    e.printStackTrace();
}

runnable.stop();

while(!threadA.isInterrupted())
{
    threadA.interrupt();
}
和输出,如:

Sleeping Main Thread.
Runnable 'Task 1' run()0
Runnable 'Task 1' run()1
Runnable 'Task 1' run()2
Runnable 'Task 1' run()3
Runnable 'Task 1' run()4
Runnable 'Task 1' run()5
Runnable 'Task 1' run()6
Runnable 'Task 1' run()7
Runnable 'Task 1' run()8
Main Thread Continued.
Runnable ended.
请注意,您实现了Runnable接口。这意味着你的类不是一个线程。因此,在runnable上调用.run将在当前线程中运行它

如果您想更多地使用多线程,我建议您阅读。

替换newThread.run;使用newThread.start

为什么我要使用关键字volatile

如果线程A在没有任何形式的同步的情况下更新exitThread,Java语言规范不要求线程B看到对exitThread的更改

实际上,线程B可能会看到更新,或者线程B可能会在一段时间后看到更新。实际发生的情况取决于您正在运行的JVM、您正在运行的操作系统以及它运行的硬件。但是,从理论上讲,线程B可能永远看不到更新

如果将volatile添加到exitThread的声明中,那么JVM需要立即将更新从线程A传播到线程B


这些规则可能看起来很奇怪,但一旦你了解了多CPU计算机中的内存系统是如何工作的,它们就更有意义了。在大多数体系结构上,访问不需要在线程之间共享的变量(即内存位置)可能比访问共享变量更有效。volatile关键字是这样说的,这个变量需要在Java中共享。

您使用continue的代码示例没有达到我的预期。我希望我的实例化线程在后台运行,只要没有设置exitThread或者线程只是完成了它的run方法。但是while循环似乎停止了程序流,因为程序等待线程完成,直到进一步执行我的java程序,有点像使用thread.join。@freeprogramer233我添加了一个示例。请注意,可运行项不是线程。如果回答了你的问题,请接受这个答案。尝试一下,没有任何区别。无论如何谢谢你!