2016-01-03 75 views
3

我有以下代码线程和中断

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"); 

    } 
} 

当线程1运行我想从运行中断threadR并因此导致

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

从threadR

我有印刷在我的代码高亮显示,其中中断应该发生

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

为什么中断不能正常工作?

+3

请修正您的代码中的缩进;目前它是无法读取的。 –

+0

你的意思是“中断不能像目前那样工作”? –

+1

“扩展了Thread implements Runnable”我建议你在其中之一中进行选择。 – MeetTitan

回答

3

你的程序有点迷宫般的线程对象。我们试着从main开始。

main中,您将创建一个对象t,该对象的类型为Threads。这意味着它是一个Thread和一个Runnable

然后,对于每个字符串,运行tthreadLthreadR并将该字符串作为参数。

没有在main你确实开始t,甚至直接运行它的run方法。

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

然后,您使用的是新的空Thread(问候)做为所被传递到一个新的Thread对象,它也有它的run方法重写一个Runnable。这是徒劳的。无论如何,greetingsFromFred已启动,并会运行循环。但greetings仍然包含有无关的greetingsFromFred缕空Thread

threadL创建另一个Thread,给你传递当前Thread(这是在maint)作为其运行的。然后,你终于开始了。它会尝试中断greetings中的线程,但正如我们所说,这是一个从未启动的非活动空线程。

你的结构应该比少了很多令人费解。尽可能使用Runnable对象来执行应该执行的操作。因此,Threads本身shoudld是Runnable,并threadR或许应该被固定到这样的事情:

public 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

但是请注意,由于您实际上并未停止catch子句中的循环,因此当线程中断时不会退出循环,并且可能会多次打印“正在退出”消息,取决于中断何时到达循环。

+0

@ RealSkeptic我正在尝试线程 - 我对线程相当陌生,只是看着我可以做的不同事情。您的导游对我了解正在发生的事情非常有用,而且我还没有开始问题线索,这是主要问题。来自你的伟大答案 – Ingram

0

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

0

要中断的线程称为greetingsFromFred而不是greetings所以如果您使greetingsFromFred可见,此更改将起作用。

 greetingsFromFred.interrupt(); //interrupt greetings thread here <------- 
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()创建并启动一个新的Thread将被打断,threadL()创建并启动一个新的Thread将中断和Threads只是存在的main()方法和threadR()线程的创建/启动和threadL()。清洁器。

中断错误的线程

正如其他人所指出的,你有这种不必要的变量,greetingsFromFred,这只是事情复杂化。您greetingsFromFred所做的一切,你应该不是为greetings做(除了构造函数)。在greetings

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

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

竞争条件下面是最细微的部分,IMO。您使用的是静态变量greetings来保存当前Thread对象R,目前L应该中断。但是这两个线程之间没有协调。我们没有理由相信,每个L会看到一个独特的Rgreetings。这是一个非常糟糕的事情。你需要做的是使greetingsvolatile,然后使R等待,直到greetings为空之前分配它,并使L等待,直到greetings不中断之前,中断它。

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然后将其置为空,它们将始终保持同步。