我正在学习java中的多线程,并且我遇到了一个我无法理解的行为。
之前,一些解释:生产者需要生产,直到列表满了。生产时,没有什么能阻止消费者消费。消费者消耗直到列表为空。当列表具有< 10个元素时,生产者才开始生产。
这是我的代码:
制作人类
class Producer extends Thread {
private MyList list;
public Producer(MyList list) {
this.list = list;
}
public void run() {
for (int i = 0; i < 1000; i++) {
try {
list.put();
} catch (InterruptedException e) {
System.out.println("I WAS INTERRUPTED");
}
}
}
}
消费
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();
}
}
对不起那堆代码,但这不是复杂的代码:)
好的,怀疑,为什么那些I WAS INTERRUPTED
从未被召唤过?
以及为什么(可能与上述相关)List doesn't have the minimun quantity to start a production
也从未被调用过?
实际输出:
....
....
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
...
...
修改
我对这些事感到困惑,我从不在代码中调用中断,但这不是我的目的。
我想知道线程何时被另一个线程'唤醒'而不是因为时间片而被jvm唤醒
答案 0 :(得分:0)
您没有调用interrupt()
方法来中断线程。在main
方法中尝试以下代码:
producer.start();
consumer.start();
producer.interrupt();
consumer.interrupt();
以下是一个示例输出:
put Thu Oct 01 10:56:10 IST 2015 at 10
List doesn't have the minimun quantity to start a production
I WAS INTERRUPTED
got Thu Oct 01 10:56:10 IST 2015 at 10
got Thu Oct 01 10:56:10 IST 2015 at 9
got Thu Oct 01 10:56:10 IST 2015 at 8
got Thu Oct 01 10:56:10 IST 2015 at 7
got Thu Oct 01 10:56:10 IST 2015 at 6
got Thu Oct 01 10:56:10 IST 2015 at 5
got Thu Oct 01 10:56:10 IST 2015 at 4
got Thu Oct 01 10:56:10 IST 2015 at 3
got Thu Oct 01 10:56:10 IST 2015 at 2
got Thu Oct 01 10:56:10 IST 2015 at 1
got Thu Oct 01 10:56:10 IST 2015 at 0
I WAS INTERRUPTED 2
put Thu Oct 01 10:56:10 IST 2015 at 0
要点注意事项(摘自官方tutorial):
interrupt
对象上调用Thread
来发送中断,以便线程被中断。为使中断机制正常工作,被中断的线程必须支持自己的中断。interrupt status
的内部标志实现中断机制。调用Thread.interrupt
设置此标志。当线程通过调用静态方法Thread.interrupted
检查中断时,中断状态被清除。非静态isInterrupted
方法(由一个线程用于查询另一个线程的中断状态)不会更改中断状态标志。