在以下Java程序中,我在HashMap中存储了3个线程,我创建了3个Th类对象,它们是从类Thread扩展的(我已经尝试过实现Runnable,但它也无效!),我想要通过分配空值3秒后停止t2我无法阻止它,我不想使用stop()方法,因为它已被弃用,它只有在我使用start方法启动线程时才有效,如果它不起作用我使用ExecutorService的execute方法
启动线程public class TestingThreads {
static HashMap<String, Thread> trds = new HashMap<>();
static Th t1 = new Th("Th1");
static Th t2 = new Th("Th2");
static Th t3 = new Th("Th3");
public TestingThreads() {
}
public static void main(String[] args) {
long ct = System.currentTimeMillis();
ExecutorService executor = Executors.newCachedThreadPool();
trds.put("t1", t1);
trds.put("t2", t2);
trds.put("t3", t3);
executor.execute(t1);
executor.execute(t2);
executor.execute(t3);
executor.shutdown();
new Thread() {
@Override
public void run() {
while (true) {
if (ct + 3000 < System.currentTimeMillis()) {
trds.put("t2", null);
trds.remove("t2");
System.out.println("Size = " + trds.size());
//I dont wanna use the stop() method as is it deprecated and it only works when I use start method to run the Thread while it is not working with execute() method of class ExecutorService
// t2.stop();
t2 = null;
break;
}
}
}
}.start();
}
}
class Th extends Thread {
String name;
Random rm = new Random();
public Th(String name) {
this.name = name;
}
@Override
public void run() {
while (!this.isInterrupted()) {
int i = rm.nextInt(500);
try {
Thread.sleep(i);
} catch (InterruptedException ex) {
}
System.out.println(name + " " + i);
}
}
}
答案 0 :(得分:1)
这只是一个线程的一个例子.. 创建一个静态volatile boolean flag。
static volatile boolean RUN_THREAD_FLAG= true;
Thread yourThread= new Thread(){
@Override
public void run() {
try{
// you can add your other conditions inside while condition
// and AND it with the FLAG
//while(RUN_THREAD_FLAG && yourCondition)
while(RUN_THREAD_FLAG){
sleep(SLEEP_TIME); //OR your task
}
} catch(Exception e){
e.printStackTrace();
}
}
};
yourThread.start();
当你想要停止线程时,只需设置 RUN_THREAD_FLAG = false
PS:你应该总是使用一些FLAG或其他方法尽可能正确地结束线程。尽量不要使用任何中断方法。
答案 1 :(得分:0)
检查您的代码,甚至无法使用t2
停止stop
,因为t2
永远不会启动,它由executor
执行。要停止t2
,您需要直接运行t2
:(对上次编辑的代码进行了更改:如果线程在sleep
中断,并执行{{},则设置中断标志= true 1}}代替t2.start()
)
executor.execute(t2)
答案 2 :(得分:0)
您也可以尝试以下类似的解决方案: -
import java.util.HashMap; import java.util.Random;
public class TestingThreads {
static Th t1 = new Th("Th1");
static Th t2 = new Th("Th2");
static Th t3 = new Th("Th3");
public TestingThreads() {
}
public static void main(String[] args) {
t1.start();
t2.start();
t3.start();
}
} class Th扩展Thread {
String name;
Random rm = new Random();
public Th(String name) {
this.name = name;
}
@Override
public void run() {
final long ct = System.currentTimeMillis()+3000;
Thread t= Thread.currentThread();
System.out.println("Running Thread is :-"+t.getName()+" "+System.currentTimeMillis());
while (true) {
if (ct < System.currentTimeMillis()) {
try{
System.out.println("Running Thread is :-"+t.getName()+" "+System.currentTimeMillis());
t.interrupt();
break;
}
catch(Exception ie)
{
System.out.println(t.getName()+" closed");
ie.printStackTrace();
}
}
}
}
}
答案 3 :(得分:0)
您使用t2.interrupt的更改将起作用,但您需要将线程更改为如下所示:(注意return语句)。
@Override
public void run() {
while (!this.isInterrupted()) {
int i = rm.nextInt(500);
try {
Thread.sleep(i);
} catch (InterruptedException ex) {
return;
}
System.out.println(name + " " + i);
}
}
当sleep方法被中断时,它会抛出InterruptedException但在它执行之前清除该标志。您必须在异常中执行某些操作才能使其正常工作。另一种方式是:
boolean running=true;
@Override
public void run() {
while (running) {
int i = rm.nextInt(500);
try {
Thread.sleep(i);
} catch (InterruptedException ex) {
running=false;
}
System.out.println(name + " " + i);
}
}
请注意,由于现在只能从一个线程访问运行,因此它不必是易失性的。
答案 4 :(得分:0)
首先,不要扩展Thread
来执行任务(=工作)!我认为你误解了执行者框架。它已经处理Threads
,你不必自己创建一个!您要做的是实现由Runnable
执行的任务(=实现Executor
)。
第二次,您的任务应该对中断敏感,即通过调用interrupt()
来中断执行线程会导致您的任务完成其工作:
public class Task implements Runnable {
public void run() {
try {
while (true) {
int i = rm.nextInt(500);
Thread.sleep(i);
System.out.println(name + " " + i);
}
} catch (InterruptedException ex) {
// restore interruption flag
Thread.currentThread.interrupt();
}
}
}
请注意,我们可以在此使用无限循环,因为Thread.sleep
将抛出InterruptedException
,一旦执行Thread
被中断,它将退出循环。 (否则我们必须自己调用Thread.currentThread().isInterrupted
来检查中断标志。)
第三次,使用ScheduledExecutorService
执行任务和取消:
ScheduledExecutorService exectuor = Executors.newScheduledThreadPool(4);
Future<?> t1f = executor.execute(new Task());
Future<?> t2f = executor.execute(new Task());
Future<?> t3f = executor.execute(new Task());
// now we can cancel tasks individually after a certain amount of time:
executor.schedule(() -> t2f.cancel(true), 3, TimeUnit.SECOND);
最后一行代码使用自Java 8以来可用的lambda表达式。如果您不想使用它们或因某些原因无法使用它们,请再次使用普通Runnable
:
executor.schedule(new Runnable() {
public void run() { t2f.cancel(true); }
}, 3, TimeUnit.SECOND);
答案 5 :(得分:0)
using a boolean variable:
package com.Exception.Demos;
public class MyRunnable implements Runnable {
boolean continueThread=true;
@Override
public void run() {
// TODO Auto-generated method stub
int i=0;
while(true){
if(continueThread){
try{
System.out.println(i++);
Thread.sleep(1000);
System.out.println("press enter to stop "+Thread.currentThread().getName());
}catch(InterruptedException exception){
exception.printStackTrace();
}
}
else{
System.out.println(Thread.currentThread().getName()+"Ended");
break;
}
}
}
}
package com.Exception.Demos;
import java.io.IOException;
public class TerminatingAThread {
public static void main(String[] args) throws IOException {
MyRunnable myRunnable=new MyRunnable();
Thread thread=new Thread(myRunnable,"Thread1");
thread.start();
System.out.println(Thread.currentThread().getName()+"thread waiting for user to press enter");
System.in.read();
myRunnable.continueThread=false;
System.out.println(Thread.currentThread().getName()+"thread ended");
}
}
答案 6 :(得分:0)
这里有两个主要的教训:
不要扩展Thread,它只会造成混淆的机会。 (即使您不使用执行程序,将要执行的逻辑与执行任务的方式分开也会提高清晰度。)
线程中断是取消任务以及如何在java.util.concurrent中关闭执行程序,你必须理解它才能有效地使用执行程序。
现在了解详情:
线程实现Runnable。当您创建Th扩展Thread的实例并将它们传递给ExecutorService时,执行程序不会在传入的线程上运行任务。它只知道你给了它一个Runnable,它继续在其一个工作线程上执行Runnable。
这就是为什么在使用ExecutorService时没有看到设置中断标志的原因。它还解释了为什么它在您启动自己的线程时有效。你正在寻找中断
this.isInterrupted()
其中this
是您传入的线程,但它是池的工作线程,而不是Th实例,它会在其上调用中断。将支票更改为
Thread.currentThread().isInterrupted()
当您捕获InterruptedException时,还应设置中断标志。当sleep方法抛出InterruptedException时,它会清除该标志(因此在下一个while循环迭代中,isInterrupted返回false)。如上所述,您应该在当前线程上调用中断,而不是this
。
等待执行程序完成的线程是不需要的(忙碌的等待它不好),你可以调用awaitTermination。
同样使用shutdown也不起作用,因为这些任务永远不会自行退出,它们必须被中断。礼貌地等待当前的任务完成,这将永远不会发生;你需要shutdownNow来中断任务。
这是一个更简单的程序来执行相同的操作,它提交3个任务并让它们在关闭之前执行3秒。注意所有我不需要做的事情,我不必在散列图中松散任务,我不需要看门狗线程来等待执行程序终止。
import java.util.*;
import java.util.concurrent.*;
public class TestThreads {
public static void main(String... args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Th("t1"));
executor.execute(new Th("t2"));
executor.execute(new Th("t3"));
Thread.sleep(3000L);
executor.shutdownNow();
executor.awaitTermination(10000L, TimeUnit.MILLISECONDS);
System.out.println("executor terminated=" + executor.isTerminated());
}
}
class Th implements Runnable {
String name;
Random rm = new Random();
public Th(String name) {
this.name = name;
}
@Override public void run() {
while (!Thread.currentThread().isInterrupted()) {
int i = rm.nextInt(500);
try {
Thread.sleep(i);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(name + " " + i);
}
}
}