Java 如何知道线程是被唤醒还是被时间分割(生产者-消费者)
我正在学习java中的多线程,我遇到了一个我无法理解的行为Java 如何知道线程是被唤醒还是被时间分割(生产者-消费者),java,multithreading,Java,Multithreading,我正在学习java中的多线程,我遇到了一个我无法理解的行为 在此之前,有一些解释:制作人需要制作,直到列表满为止。生产时,没有任何东西能阻止消费者消费。消费者消费,直到列表为空。只有当列表中有您没有调用interrupt()方法来中断线程时,生产者才开始生产。在main方法中尝试以下代码: producer.start(); consumer.start(); producer.interrupt(); consumer.interrupt(); 以下是一个示例输出: 2015年10月1日星期
在此之前,有一些解释:制作人需要制作,直到列表满为止。生产时,没有任何东西能阻止消费者消费。消费者消费,直到列表为空。只有当列表中有您没有调用
interrupt()
方法来中断线程时,生产者才开始生产。在main
方法中尝试以下代码:
producer.start();
consumer.start();
producer.interrupt();
consumer.interrupt();
以下是一个示例输出:
2015年10月1日星期四10:56:10国际标准时间10点
列表没有开始生产的最小数量
我被打断了
获得2015年10月1日星期四10:56:10 IST 10点
获得2015年10月1日星期四10:56:10国际标准时间9点
获得2015年10月1日星期四10:56:10 IST 8点
获得2015年10月1日星期四10:56:10 IST 7点
获得2015年10月1日星期四10:56:10 IST 6点
2015年10月1日星期四10:56:10国际标准时间5点
2015年10月1日星期四10:56:10国际标准时间4点
2015年10月1日星期四10:56:10国际标准时间3点
2015年10月1日星期四10:56:10国际标准时间2点
2015年10月1日星期四10:56:10国际标准时间1点
已于2015年10月1日星期四10:56:10获取0
我被打断了
将2015年10月1日星期四10:56:10 IST设置为0
注意事项(摘自官方文件):
线程通过调用要中断的线程的thread
对象上的interrupt
来发送中断。为了使中断机制正常工作,被中断的线程必须支持自己的中断
中断机制使用称为中断状态的内部标志实现。调用Thread.interrupt
设置此标志。当线程通过调用静态方法thread.interrupted
检查中断时,中断状态被清除。一个线程用来查询另一个线程的中断状态的非静态isInterrupted
方法不会更改中断状态标志
main
中的变量名称不匹配,请更正它没有被调用,因为您没有中断代码中的任何线程。您需要调用Thread.interrupt()
来中断线程。请检查productor、consumidor的变量名。是否应该是“生产者”和“消费者”?@ErwinBolwidt然后notifyAll()
在这种情况下没有帮助?您的线程是否被唤醒或时间切片是无关紧要的,并且无法从代码中检测。你的问题毫无意义。我怎么知道某个线程是否被“唤醒”,而不是从时间上恢复-slice@JohnnyWiller你不能。如果你可以的话,会有什么不同?@JohnnyWiller“睡眠”和“醒来”的发生是因为你的程序所做的事情。线程只能通过调用使其睡眠的方法来“睡眠”(例如,thread.sleep()
,object.wait()
)。当方法调用返回时,这意味着您的线程被“唤醒”。另一方面,时间切片对于程序来说是完全不可见的。它不是语言的一部分,也不是任何库调用都能做到的。它只是发生了,你的程序甚至无法知道它发生的时间和地点。
class Consumer extends Thread {
private MyList list;
public Consumer(MyList list) {
this.list = list;
}
public void run() {
for (int i = 0; i < 1000; i++) {
try {
list.get();
} catch (InterruptedException e) {
System.out.println("I WAS INTERRUPTED 2");
}
}
}
}
public class MyList {
private String[] dates = new String[100];
private int index = -1;
public int getIndex() {
return index;
}
public synchronized void put() throws InterruptedException {
if ((getIndex() + 1) == 100) {
System.out.println("List is full");
wait();
}
/**
* Here I need to know if this thread was woke up by the consumer, or it was 'restaured' due time-slice
*
*/
if (Thread.currentThread().isInterrupted() && getIndex() >= 10) {
System.out.println("List doesn't have the minimun quantity to start a production");
wait();
}
dates[++index] = new Date().toString();
System.out.println("put " + dates[index] + " at " + index);
notifyAll();
}
public synchronized void get() throws InterruptedException {
if (getIndex() < 0)
wait();
System.out.println("got " + dates[index--] + " at " + (index + 1));
/**
* Basically, to this example work I would need to put, if (getIndex() < 10) notifyAll() here,
* but that is a behavior for the producer and should not be in the consumer
*
*/
notifyAll();
}
}
public class Main {
public static void main(String[] args) {
MyList list = new MyList();
Thread producer = new Producer(list);
Thread consumer = new Consumer(list);
producer.start();
consumer.start();
}
}
....
....
put Thu Oct 01 02:15:12 BRT 2015 at 93
put Thu Oct 01 02:15:12 BRT 2015 at 94
put Thu Oct 01 02:15:12 BRT 2015 at 95
put Thu Oct 01 02:15:12 BRT 2015 at 96
put Thu Oct 01 02:15:12 BRT 2015 at 97
put Thu Oct 01 02:15:12 BRT 2015 at 98
put Thu Oct 01 02:15:12 BRT 2015 at 99
List is full
got Thu Oct 01 02:15:12 BRT 2015 at 99
put Thu Oct 01 02:15:12 BRT 2015 at 99 <- this wouldn't happen
List is full
got Thu Oct 01 02:15:12 BRT 2015 at 99
put Thu Oct 01 02:15:12 BRT 2015 at 99 <- this wouldn't happen
List is full
...
...
producer.start();
consumer.start();
producer.interrupt();
consumer.interrupt();