我有一个Jersey资源类,该类基本上实例化了一个特定的线程,该线程由intern创建一堆线程来执行一些工作。 Jersey资源不会等待所有线程完成其工作,它只是在线程实例化后立即将结果(特别是jobID
)返回给客户端,并将jobID
与线程对象一起保留在MAP中。
现在,我的要求是使用jobID
作为输入来创建新的资源类,其他资源已创建并存储在Map中。这个新资源假定杀死所有与该jobID
运行的线程。
我尝试使用jobID
将线程存储在map中,然后尝试中断该特定线程,但实际上并未停止所有子进程。
如何用最佳解决方案来做到这一点?
以下是供参考的代码段
package com.izq.eam.cps.dal2;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
@Path("Test")
public class TestResource {
public static Map<Integer, Thread> myThreadMap = new HashMap<>();
@Path("/startJob")
@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Integer cspStartMarkingSession(String job_details) {
Integer jobId = null;
try {
if (job_details != null) {
jobId = createJob(job_details);
}
} catch (Exception e) {
throw new WebApplicationException(e);
}
return jobId;
}
private Integer createJob(String job_details) {
Random rand = new Random();
// Generate random integers in range 0 to 999
Integer JOBID = rand.nextInt(1000);
Thread t = new Thread() {
@Override
public void run() {
MyNewThread t = new MyNewThread(job_details);
t.start();
}
};
t.start();
myThreadMap.put(JOBID, t);
return JOBID;
}
class MyNewThread extends Thread {
String job_details;
public MyNewThread(String job_details2) {
this.job_details = job_details;
}
@Override
public void run() {
synchronized (MyNewThread.class) {
try {
System.out.println("JOB DETAILS " + this.job_details);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Path("/stopJob")
@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public String cspStopMarkingSession(Integer jobID) {
Thread t = myThreadMap.get(jobID);
if (t.isAlive()) {
t.interrupt(); // This is not actually stopping all the child thread instantiated by Thread t ;
}
return "JOB Stopping is successfull";
}
}
编辑。...
我能够通过其他方式解决此问题。
基本上,我要尝试的是在我的startjob方法中,我已经启动了linux命令,这将花费一定的时间来提供最终输出,但是它将任务的进度推进到shell-std.out,并且在它会写入shell-std.err
的任何错误下面是触发linux命令的代码,运行命令后,我已将线程池用于不同的任务
final Process process = Runtime.getRuntime().exec(command.toString()); // To run linux command
threadPool.submit(() -> drainToBufferedStream(process.getInputStream(), standardOutput)); // to capture progress of task
threadPool.submit(() -> drainToBufferedStream(process.getErrorStream(), standardError)); // to capture any error
threadPool.submit(() -> waitForProcessExit(process)); // final output
我将这个线程池对象传递回调用方法,并使用JOBID将其存储在MAP中
每当我使用stopJob方法时,我都会从MAP中获取线程池对象,并尝试使用threadPool.shutdownnow()方法关闭线程。但是,不能保证使用shutdownnow()方法杀死所有线程。
后来,我确实将Process对象本身存储在MAP中,并在stopJob调用时试图销毁process.destroy(),这杀死了正在执行命令的进程,这样我使用进程对象的所有线程最终都被杀死了。
答案 0 :(得分:0)
您的子线程不会被打断。
几件事要注意:
只有一个线程能够获得对MyNewThread.class
的锁定
而其他人将在synchronized()
无法
获取锁,更不用说wait()
要使用Object.wait()
暂停线程,线程必须拥有该对象上的隐式锁。您不能保证它是您的
synchronized()
获得单例的隐式锁定
在MyNewThread.class
实例上调用wait()
时代表this
使用synchronized(someSharedObject)
,然后使用someSharedObject.wait()
和someSharedObject.notify()
(或notifyAll
),这将意味着更改子线程的操作方式
OR 将Thread.sleep(timeInMillis)
与while()
进行循环测试,以对线程的isInterrupted()
进行循环测试。这样,您将允许该线程占用的CPU份额可供其他线程使用,并使您的线程被调度回去以再次测试isInterrupted()
;如果为false,则再次调用sleep()
。通过这种方式,您的子线程对中断的响应能力可以(大致)由睡眠时间来调节。
答案 1 :(得分:0)
该代码正在插入子线程,因为您要为每个作业创建两个线程。我不清楚这样做的目的是什么。您的代码正在创建两个线程,一个在create-Job方法中创建,另一个在run方法中创建。您没有将在run方法中创建的线程放入映射中。
Thread t = new Thread() {
@Override
public void run() {
MyNewThread t = new MyNewThread(job_details);
t.start();
}
};
t.start();