java 生产者消费者 线程优先级问题
发布网友
发布时间:2022-05-01 07:48
我来回答
共5个回答
热心网友
时间:2022-06-26 07:54
1、容器或者线程在生产或消费时需要先判断容器是否为空、是否已满,容器没有自定义的话,就要在线程类中每次生产之前判断容器是否已满(这个已经由容器判断),在消费时要判断容器是否为空
2、一般,线程同步最好用synchronized关键字锁定同步代码,然后通过wait()和notify()方法实现线程同步,不过容器容量大一点才能看到效果。代码如下:
class BQProc implements Runnable {
private BlockingQueue<Integer> queue;
public BQProc(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
synchronized(queue) {
for (int proct = 1; proct <= 10; proct++) {
try {
if(queue.size() == 5) {
queue.wait();
}
queue.put(proct);// 放进去一个
System.out.println("放在 --> " + this.queue.size());
queue.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class BQConsume implements Runnable {
private BlockingQueue<Integer> queue;
public BQConsume(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
synchronized(queue) {
for (int i = 1; i <= 10; i++) {
try {
if(queue.isEmpty()) {
queue.wait();
}
System.out.println("拿出 <-- " + this.queue.size());
queue.take();// 拿出来一个
queue.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
放在 --> 1
放在 --> 2
放在 --> 3
放在 --> 4
放在 --> 5
拿出 <-- 5
拿出 <-- 4
拿出 <-- 3
拿出 <-- 2
拿出 <-- 1
放在 --> 1
放在 --> 2
放在 --> 3
放在 --> 4
放在 --> 5
拿出 <-- 5
拿出 <-- 4
拿出 <-- 3
拿出 <-- 2
拿出 <-- 1
PS:当基数大到一定程度才可以看到想要的结果
3、如果一定要用Thread.sleep()实现的话可以用循环控制,代码如下:
class BQProc implements Runnable {
private BlockingQueue<Integer> queue;
public BQProc(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
for (int proct = 1; proct <= 10; proct++) {
try {
while(queue.size() == 5) {
Thread.sleep(1000);
}
Thread.sleep((int) (Math.random() * 1000));
queue.put(proct);// 放进去一个
System.out.println("放在 --> " + this.queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class BQConsume implements Runnable {
private BlockingQueue<Integer> queue;
public BQConsume(BlockingQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
for (int i = 1; i <= 10; i++) {
try {
while(queue.isEmpty()) {
Thread.sleep(1000);
}
Thread.sleep((int) (Math.random() * 1000));
System.out.println("拿出 <-- " + this.queue.size());
queue.take();// 拿出来一个
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果:
放在 --> 1
放在 --> 2
拿出 <-- 2
拿出 <-- 1
放在 --> 1
拿出 <-- 1
放在 --> 1
放在 --> 2
拿出 <-- 2
放在 --> 2
放在 --> 3
拿出 <-- 3
拿出 <-- 2
放在 --> 2
放在 --> 3
拿出 <-- 3
放在 --> 3
拿出 <-- 3
拿出 <-- 2
拿出 <-- 1
热心网友
时间:2022-06-26 07:54
queue.put(proct);//将指定元素添加到此队列中,如果没有可用空间,将一直等待 .
queue.take();//检索并移除此队列的头部,如果此队列不存在任何元素,则一直等待
不管你设置优先级..肯定是先执行queue.put() 因为 里面没有值.
当queue.put()抢到线程的时候一次执行5次(应该可以更多,因为你*了可用空间5个值),所以它才会停止了让给queue.take()
你可以在
System.out.println("放在 --> "+ this.queue.size());
Thread.sleep(1000);
后面加入一个停止1秒钟.就能看到效果了
热心网友
时间:2022-06-26 07:55
真正的原因是---------------------------
第一个时间永远等于0,等于是sleep(0)了,不信的话打出来看看就知道了。
就是这句话Thread.sleep((int) Math.random() * 3000);
少了一个括号发现没,应该是
Thread.sleep((int) (Math.random() * 3000));
但你的第二个没少括号,所以第一个不会sleep,第二个会,就造成这种结果了
加上括号就ok
热心网友
时间:2022-06-26 07:56
不要郁闷,这是正确的。
你需要仔细品味javadoc:api/java/util/concurrent/package-summary.html#MemoryVisibility
其实从另一个角度讲,这种使用方法不对。你只有一个线程。但实际上更多的情况下用于多次线程。多次?是的,一个线程多次执行,多个线程一次执行。
热心网友
时间:2022-06-26 07:56
try {
Thread.sleep((int) (Math.random() * 3000));
queue.put(proct);//放进去一个
System.out.println("放在 --> " + this.queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
你看看你这段代码中的Thread.sleep((int) Math.random() * 3000);
这句出问题了,正确的是Thread.sleep((int) (Math.random() * 3000));
你(int) Math.random() * 3000这里结果一直是0,这个线程根本没停,你把那个0到1的随即值取整就是0了,0*3000就是0了,就错了。
我也犯过这样的错误。netbeans里自动取整就是这么取的。我是拿颜色结果不变色了。