我试图为一个线程提供一个解决方案来暂停和恢复其中断的位置。
所以这是一个模拟我的问题的示例代码:2个线程在后台运行:taskThread
& busyThread
。当busyThread
位于系统繁忙区域时,taskThread
必须立即进行alt /暂停,并从中断处继续。例如,如果在任务C(已完成)暂停taskThread
,则应在D处继续。
我尝试在taskThread上使用wait,notify但没有成功。
public class Test
{
private Thread taskThread;
private Thread busyThread;
public static void main(String args[]) throws Exception
{
Test t = new Test();
t.runTaskThread();
t.runBusyThread();
}
public void runTaskThread()
{
taskThread = new Thread(new Runnable(){
@Override
public void run()
{
for (int x=0; x<100; x++)
{
try
{
System.out.println("I'm doing task A for process #"+x);
Thread.sleep(1000);
System.out.println("I'm doing task B for process #"+x);
Thread.sleep(200);
System.out.println("I'm doing task C for process #"+x);
Thread.sleep(300);
System.out.println("I'm doing task D for process #"+x);
Thread.sleep(800);
System.out.println("\n\n");
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}});
taskThread.start();
}
public void runBusyThread()
{
busyThread = new Thread(new Runnable(){
@Override
public void run()
{
while (true)
{
Random rand = new Random();
int randomNum = rand.nextInt(1000);
if (randomNum<400)
{
System.out.println("Wait...system is busy!!!");
try
{ //what should come here to to signal taskThread to paused
Thread.sleep(3000);
//what should come here to to signal taskThread to resume
} catch (InterruptedException e)
{
}
} else
{
try
{
Thread.sleep(300);
} catch (InterruptedException e)
{
}
}
}
}});
busyThread.start();
}
}
答案 0 :(得分:1)
并发包中有两个非常有用的类 - CountDownLatch
和CyclicBarrier
。如果您只需要此行为一次,则可能需要第一个(因为它无法重置)。
线程1将等待直到线程2通知。一旦它被倒计数到0,线程1将永远不会再次阻塞await()
:
CountDownLatch cdl = new CountDownLatch(1);
// thread 1:
cdl.await();
// thread 2:
cdl.countDown();
线程将在await()
处阻塞,直到正好有两个线程在等待:
CyclicBarrier barrier = new CyclicBarrier(2);
// both threads:
barrier.await();
修改强>
以下是我在修改代码时提出的问题,但我不清楚这是否是预期的行为。
请注意volatile
上的CountDownLatch
关键字 - 这里非常重要,否则taskThread
可能会缓存初始对象(new CountDownLatch(0)
),因此永远不会阻止。
public class Test {
private Thread taskThread;
private Thread busyThread;
private volatile CountDownLatch cdl = new CountDownLatch(0);
public static void main(String args[]) throws Exception {
Test t = new Test();
t.runTaskThread();
t.runBusyThread();
}
public void runTaskThread() {
taskThread = new Thread(() -> {
for (int x = 0; x < 100; x++) {
waitIfSystemBusy();
System.out.println("I'm doing task A for process #" + x);
sleep(1000);
waitIfSystemBusy();
System.out.println("I'm doing task B for process #" + x);
sleep(200);
waitIfSystemBusy();
System.out.println("I'm doing task C for process #" + x);
sleep(300);
waitIfSystemBusy();
System.out.println("I'm doing task D for process #" + x);
sleep(800);
System.out.println("\n\n");
}
});
taskThread.start();
}
public void runBusyThread() {
busyThread = new Thread(() -> {
while (true) {
Random rand = new Random();
int randomNum = rand.nextInt(1000);
if (randomNum < 400) {
System.out.println("Wait...system is busy!!!");
cdl = new CountDownLatch(1); // signal taskThread to pause
sleep(3000);
cdl.countDown(); // signal taskThread to resume
} else {
sleep(300);
}
}
});
busyThread.start();
}
private void waitIfSystemBusy() {
try {
cdl.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
答案 1 :(得分:0)
可以使用弃用的方法Thread.suspend/resume
来完成。
它们因为容易出现死锁而被弃用,而像锁这样的并发机制以设计的显式方式运行(但仍然容易出现死锁)。
答案 2 :(得分:0)
我建议您创建一个implements Runnable
的课程,该课程只是跟踪您所在的stages
仅作为示例(请相应更改)
class MyRunnable implements Runnable {
private int stage = 0; // if you want it gloabally, then use static
@Override
public void run() {
try{
switch(stage){
case 1:
System.out.println("1");
stage++;
case 2:
System.out.println("2");
Thread.sleep(2000);
stage++;
default:
stage = 0;
}
}catch (Exception e){
}
}
}
现在要使用这样的类,你只需要创建一个新的线程 例如:
public static void main(String[] args) throws Exception{
MyRunnable myRunnable=new MyRunnable();
new Thread(myRunnable).start(); //it prints 1
Thread.sleep(1000);
new Thread(myRunnable).start(); //prints 2 follow by 2 sec sleep
}
注意:强>
这个例子并不是为了准确回答这个问题,而是为了说明如何做到这一点。
编辑1:
应该来这里告诉taskThread暂停
taskThread.interupt();
应该发出什么来表示taskThread恢复
taskThread=new Thread(myRunnable);
taskThread.start();
答案 3 :(得分:0)
而不是sleep()我更喜欢wait()和notifyAll()。 有一个布尔systemBusy,实现get和set方法; 现在在thread1
run(){
synchronize(something){
while(isSystemBusy()){
try{
wait();}
catch{}
}
}
}
和另一个帖子
run(){
setSystemBusy(true);
//piece of code
//task finished
notifyAll();
setSystemBusy(false);
}
你可以在多个等待线程中使用它,只需记住在通知all之后设置适当的条件为false。