线程和中断

时间:2016-01-03 11:15:55

标签: java multithreading interrupt

我有以下代码

package threads;

import java.util.ArrayList;
import java.util.List;

public class Threads extends Thread implements Runnable {

    private final List<Thread> threadList = new ArrayList<>();
    private String f, l;
    private Thread greetings1, greetings;

    public static void main(String[] args) {

        String[] elements = { "Tim", "Fred", "Jeff", "Scott" };
        Threads t = new Threads();
        for (String e : elements) {
            t.threadL(e);

            t.threadR(e);
        }

        for (int index = 0; index < t.threadList.size(); index++) {
            // blank at the moment

        }
    }

    public void threadR(String f) {
        greetings = new Thread(f);

        Thread greetingsFromFred = new Thread(greetings) {

            @Override
            public void run() {
                for (int i = 1; i < 5; i++) {
                    try {
                        System.out.println("Main Thread: " + i + " " + f);
                        Thread.sleep(5000);

                    } catch (InterruptedException ex) {
                        System.out.println("Main thread interrupted.");

                    }
                    System.out.println("Main thread exiting.");
                }
            }
        };
        greetingsFromFred.start();
    }

    public List<Thread> threadL(String l) {
        greetings1 = new Thread(this);

        this.l = l;
        greetings1.start();

        threadList.add(greetings1);

        return (threadList);

    }

    @Override
    public void run() {

        greetings.interrupt(); // interrupt greetings thread here <-------

        System.out.println("Greetings from " + l + "! threadL");

    }
}

当threadL运行时,我想中断threadR的运行,从而导致

 System.out.println("Main thread interrupted.");

从threadR打印

我在我的代码中突出显示了应该发生中断的事件

 greetings.interrupt();  //interrupt greetings thread here <-------

为什么中断不能像现在这样工作?

4 个答案:

答案 0 :(得分:3)

你的程序是一个迷宫般的线程对象。让我们尝试从main开始关注它。

main中,您可以创建t类型的对象Threads。这意味着它是ThreadRunnable

然后,对于每个字符串,您使用该字符串作为参数运行t&#39; threadLthreadR

main中没有任何地方您实际开始t,甚至直接运行run方法。

然后,在threadR中,您创建一个新的空Thread并将其分配给greetings

然后,您将新的空Thread(问候语)用作Runnable,并将其传递给同时拥有Thread方法的新run对象覆盖。这是徒劳的。在任何情况下,greetingsFromFred都会启动,并将运行循环。但是greetings仍然包含与Thread主题无关的空greetingsFromFred

threadL中,您创建了另一个Thread,您将当前Threadt中的main)作为其可运行对象传递到该greetings。然后你终于开始了。它将尝试中断Runnable中的线程,但正如我们所说,这是一个从未启动的非活动空线程。

你的结构应该比那复杂得多。尽可能使用Threads个对象来处理应该执行的事情。因此,Runnable本身应该是threadRpublic void threadR(String f) { Runnable greetingsFromFred = new Runnable() { @Override public void run() { for (int i = 1; i < 5; i++) { try { System.out.println("Main Thread: " + i + " " + f); Thread.sleep(5000); } catch (InterruptedException ex) { System.out.println("Main thread interrupted."); } System.out.println("Main thread exiting."); } } }; greetings = new Thread(greetingsFromFred, f); greetings.start(); } 应该固定为这样的内容:

greetings

这样,Thread将是Runnable,它将运行您在f 中创建的循环,并且名称为{{ 1}}。

但请注意:由于您实际上没有在catch子句中停止循环,因此当线程中断时您不会退出循环,并且您可能已经&#34;退出&#34;消息打印不止一次,具体取决于中断何时到达循环。

答案 1 :(得分:0)

您需要中断greetingsFromFred。这是正在启动并实际运行的线程。线程greetings永远不会运行。是仅作为r​​unnable传递给其他线程。你为什么甚至在一个线程的构造函数中传递一些其他线程?整个设计非常腥。我认为你对线程/ runnable以及何时以及如何使用它感到困惑。

答案 2 :(得分:0)

您要中断的主题称为greetingsFromFred而非greetings,因此只要您greetingsFromFred可见,此更改就会有效。

       greetingsFromFred.interrupt();  //interrupt greetings thread here <-------

答案 3 :(得分:0)

正如其他人所指出的,这里有几个问题。

不必要的继承

您的班级Threads有一个run()方法,可以中断分配给greetings的任何线程,但RL都不会继承run() } 方法。 R扩展Thread并覆盖run(),而L只是扩展Thread而不会覆盖。这种结构毫无意义。

鉴于此,run()似乎应该覆盖此L方法。

如果您实现这一目标,则Threads无需覆盖Thread或实施Runnable。您可以完全取消,并RL各自覆盖Thread(使用Thread(String)构造函数)。

public class Threads {
...
    public List<Thread> threadL(String l) {
        greetings1 = new Thread(l) {
            @Override
            public void run() {
                greetings.interrupt(); // interrupt greetings thread here <-------
                System.out.println("Greetings from " + l + "! threadL");
            }
        ...
    }
}

现在threadR()创建并启动一个将被中断的新ThreadthreadL()创建并启动一个将会中断的新Thread,并Threads仅存在main()方法以及threadR()threadL()中线程的创建/启动。清洁器。

中断错误的线程

正如其他人所指出的那样,你有这个不必要的变量greetingsFromFred,这只会使问题复杂化。您为greetingsFromFred所做的一切都应该代替greetings(构造函数除外)。

public void threadR(String f) {
    greetings = new Thread(f) {

        @Override
        public void run() {
            ...
        }
    greetings.start();
}

greetings

上的竞争条件

这是IMO中最微妙的部分。您正在使用静态变量greetings来保存当前Thread应该中断的当前R对象L。但是这两个线程之间没有协调。我们没有理由相信每个L会在R中看到唯一的greetings。那是非常糟糕的事情。您需要做的是让greetings volatile,然后让R等到greetings为空,然后再分配它,让L等到greetings在中断它之前不是null。

private volatile Thread greetings;
...
public void threadR(String f) {
    while (greetings != null);
    greetings = new Thread(f) {
...
public void threadL(String l) {
    Thread greetings1 = new Thread(l) {
        @Override
        public void run() {
            while (greetings == null);
...

请注意while(...);的使用。尾随分号是一个空的陈述。这个结构只是说要检查条件,直到它为假,然后继续。由于R永远不会继续进行,直到它有null然后设置它,并且L永远不会继续进行,直到它有non-null然后使其为空,它们将始终保持同步