- 浏览: 75987 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
lovexz365:
学习了,刚刚遇到这个问题
java.io.CharConversionException:EOF异常 -
胡小米:
liuInsect 写道你这里的内存索引根本就没用嘛... ...
Lucene(NIOFSDirectory、RAMDirectory) -
liuInsect:
你这里的内存索引根本就没用嘛... 都是把索引建立在了硬盘上 ...
Lucene(NIOFSDirectory、RAMDirectory)
生产者消费者问题是研究多线程程序时绕不开的问题,它的描述是有一块生产者和消费者共享的有界缓冲区,生产者往缓冲区放入产品,消费者从缓冲区取走产品,这个过程可以无休止的执行,不能因缓冲区满生产者放不进产品而终止,也不能因缓冲区空消费者无产品可取而终止。
解决生产者消费者问题的方法有两种,一种是采用某种机制保持生产者和消费者之间的同步,一种是在生产者和消费者之间建立一个管道。前一种有较高的效率并且可控制性较好,比较常用,后一种由于管道缓冲区不易控制及被传输数据对象不易封装等原因,比较少用。
同步问题的核心在于,CPU是按时间片轮询的方式执行程序,我们无法知道某一个线程是否被执行、是否被抢占、是否结束等,因此生产者完全可能当缓冲区已满的时候还在放入产品,消费者也完全可能当缓冲区为空时还在取出产品。
现在同步问题的解决方法一般是采用信号或者加锁机制,即生产者线程当缓冲区已满时放弃自己的执行权,进入等待状态,并通知消费者线程执行。消费者线程当缓冲区已空时放弃自己的执行权,进入等待状态,并通知生产者线程执行。这样一来就保持了线程的同步,并避免了线程间互相等待而进入死锁状态。
JAVA语言提供了独立于平台的线程机制,保持了”write once, run anywhere”的特色。同时也提供了对同步机制的良好支持。
在JAVA中,一共有四种方法支持同步,其中三个是同步方法,一个是管道方法。
1. 方法wait()/notify()
2. 方法await()/signal()
3. 阻塞队列方法BlockingQueue
4. 管道方法PipedInputStream/PipedOutputStream
下面我们看各个方法的实现:
1. 方法wait()/notify()
wait()和notify()是根类Object的两个方法,也就意味着所有的JAVA类都会具有这个两个方法,为什么会被这样设计呢?我们可以认为所有的对象默认都具有一个锁,虽然我们看不到,也没有办法直接操作,但它是存在的。
wait()方法表示:当缓冲区已满或空时,生产者或消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让另一个线程开始执行;
notify()方法表示:当生产者或消费者对缓冲区放入或取出一个产品时,向另一个线程发出可执行通知,同时放弃锁,使自己处于等待状态。
下面是一个例子代码:
import java.util.LinkedList;
public class Sycn1{
private LinkedList<Object> myList =new LinkedList<Object>();
private int MAX = 10;
public Sycn1(){
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn1 s1 = new Sycn1();
s1.start();
}
class Producer extends Thread{
public void run(){
while(true){
synchronized(myList){
try{
while(myList.size() == MAX){
System.out.println("warning: it's full!");
myList.wait();
}
Object o = new Object();
if(myList.add(o)){
System.out.println("Producer: " + o);
myList.notify();
}
}catch(InterruptedException ie){
System.out.println("producer is interrupted!");
}
}
}
}
}
class Consumer extends Thread{
public void run(){
while(true){
synchronized(myList){
try{
while(myList.size() == 0){
System.out.println("warning: it's empty!");
myList.wait();
}
Object o = myList.removeLast();
System.out.println("Consumer: " + o);
myList.notify();
}catch(InterruptedException ie){
System.out.println("consumer is interrupted!");
}
}
}
}
}
}
2. 方法await()/signal()
在JDK5.0以后,JAVA提供了新的更加健壮的线程处理机制,包括了同步、锁定、线程池等等,它们可以实现更小粒度上的控制。await()和signal()就是其中用来做同步的两种方法,它们的功能基本上和wait()/notify()相同,完全可以取代它们,但是它们和新引入的锁定机制Lock直接挂钩,具有更大的灵活性。
下面是一个例子代码:
import java.util.LinkedList;
import java.util.concurrent.locks.*;
public class Sycn2{
private LinkedList<Object> myList = new LinkedList<Object>();
private int MAX = 10;
private final Lock lock = new ReentrantLock();
private final Condition full = lock.newCondition();
private final Condition empty = lock.newCondition();
public Sycn2(){
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn2 s2 = new Sycn2();
s2.start();
}
class Producer extends Thread{
public void run(){
while(true){
lock.lock();
try{
while(myList.size() == MAX){
System.out.println("warning: it's full!");
full.await();
}
Object o = new Object();
if(myList.add(o)){
System.out.println("Producer: " + o);
empty.signal();
}
}catch(InterruptedException ie){
System.out.println("producer is interrupted!");
}finally{
lock.unlock();
}
}
}
}
class Consumer extends Thread{
public void run(){
while(true){
lock.lock();
try{
while(myList.size() == 0){
System.out.println("warning: it's empty!");
empty.await();
}
Object o = myList.removeLast();
System.out.println("Consumer: " + o);
full.signal();
}catch(InterruptedException ie){
System.out.println("consumer is interrupted!");
}finally{
lock.unlock();
}
}
}
}
}
3. 阻塞队列方法BlockingQueue
BlockingQueue也是JDK5.0的一部分,它是一个已经在内部实现了同步的队列,实现方式采用的是我们的第2种await()/signal()方法。它可以在生成对象时指定容量大小。
它用于阻塞操作的是put()和take()方法。
put()方法类似于我们上面的生产者线程,容量最大时,自动阻塞。
take()方法类似于我们上面的消费者线程,容量为0时,自动阻塞。
下面是一个例子代码:
import java.util.concurrent.*;
public class Sycn3{
private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10);
private int MAX = 10;
public Sycn3(){
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn3 s3 = new Sycn3();
s3.start();
}
class Producer extends Thread{
public void run(){
while(true){
//synchronized(this){
try{
if(queue.size() == MAX)
System.out.println("warning: it's full!");
Object o = new Object();
queue.put(o);
System.out.println("Producer: " + o);
}catch(InterruptedException e){
System.out.println("producer is interrupted!");
}
//}
}
}
}
class Consumer extends Thread{
public void run(){
while(true){
//synchronized(this){
try{
if(queue.size() == 0)
System.out.println("warning: it's empty!");
Object o = queue.take();
System.out.println("Consumer: " + o);
}catch(InterruptedException e){
System.out.println("producer is interrupted!");
}
//}
}
}
}
}
你发现这个例子中的问题了吗?
如果没有,我建议你运行一下这段代码,仔细观察它的输出,是不是有下面这个样子的?为什么会这样呢?
…
warning: it's full!
Producer: java.lang.object@4526e2a
…
你可能会说这是因为put()和System.out.println()之间没有同步造成的,我也这样认为,我也这样认为,但是你把run()中的synchronized前面的注释去掉,重新编译运行,有改观吗?没有。为什么?
这是因为,当缓冲区已满,生产者在put()操作时,put()内部调用了await()方法,放弃了线程的执行,然后消费者线程执行,调用take()方法,take()内部调用了signal()方法,通知生产者线程可以执行,致使在消费者的println()还没运行的情况下生产者的println()先被执行,所以有了上面的输出。run()中的synchronized其实并没有起什么作用。
对于BlockingQueue大家可以放心使用,这可不是它的问题,只是在它和别的对象之间的同步有问题。
对于这种多重嵌套同步的问题,以后再谈吧,欢迎大家讨论啊!
4. 管道方法PipedInputStream/PipedOutputStream
这个类位于java.io包中,是解决同步问题的最简单的办法,一个线程将数据写入管道,另一个线程从管道读取数据,这样便构成了一种生产者/消费者的缓冲区编程模式。
下面是一个例子代码,在这个代码我没有使用Object对象,而是简单的读写字节值,这是因为PipedInputStream/PipedOutputStream不允许传输对象,这是JAVA本身的一个bug,具体的大家可以看sun的解释:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4131126
import java.io.*;
public class Sycn4{
private PipedOutputStream pos;
private PipedInputStream pis;
//private ObjectOutputStream oos;
//private ObjectInputStream ois;
public Sycn4(){
try{
pos = new PipedOutputStream();
pis = new PipedInputStream(pos);
//oos = new ObjectOutputStream(pos);
//ois = new ObjectInputStream(pis);
}catch(IOException e){
System.out.println(e);
}
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn4 s4 = new Sycn4();
s4.start();
}
class Producer extends Thread{
public void run() {
try{
while(true){
int b = (int) (Math.random() * 255);
System.out.println("Producer: a byte, the value is " + b);
pos.write(b);
pos.flush();
//Object o = new MyObject();
//oos.writeObject(o);
//oos.flush();
//System.out.println("Producer: " + o);
}
}catch(Exception e){
//System.out.println(e);
e.printStackTrace();
}finally{
try{
pos.close();
pis.close();
//oos.close();
//ois.close();
}catch(IOException e){
System.out.println(e);
}
}
}
}
class Consumer extends Thread{
public void run(){
try{
while(true){
int b = pis.read();
System.out.println("Consumer: a byte, the value is " + String.valueOf(b));
//Object o = ois.readObject();
//if(o != null)
//System.out.println("Consumer: " + o);
}
}catch(Exception e){
//System.out.println(e);
e.printStackTrace();
}finally{
try{
pos.close();
pis.close();
//oos.close();
//ois.close();
}catch(IOException e){
System.out.println(e);
}
}
}
}
//class MyObject implements Serializable {
//}
}
解决生产者消费者问题的方法有两种,一种是采用某种机制保持生产者和消费者之间的同步,一种是在生产者和消费者之间建立一个管道。前一种有较高的效率并且可控制性较好,比较常用,后一种由于管道缓冲区不易控制及被传输数据对象不易封装等原因,比较少用。
同步问题的核心在于,CPU是按时间片轮询的方式执行程序,我们无法知道某一个线程是否被执行、是否被抢占、是否结束等,因此生产者完全可能当缓冲区已满的时候还在放入产品,消费者也完全可能当缓冲区为空时还在取出产品。
现在同步问题的解决方法一般是采用信号或者加锁机制,即生产者线程当缓冲区已满时放弃自己的执行权,进入等待状态,并通知消费者线程执行。消费者线程当缓冲区已空时放弃自己的执行权,进入等待状态,并通知生产者线程执行。这样一来就保持了线程的同步,并避免了线程间互相等待而进入死锁状态。
JAVA语言提供了独立于平台的线程机制,保持了”write once, run anywhere”的特色。同时也提供了对同步机制的良好支持。
在JAVA中,一共有四种方法支持同步,其中三个是同步方法,一个是管道方法。
1. 方法wait()/notify()
2. 方法await()/signal()
3. 阻塞队列方法BlockingQueue
4. 管道方法PipedInputStream/PipedOutputStream
下面我们看各个方法的实现:
1. 方法wait()/notify()
wait()和notify()是根类Object的两个方法,也就意味着所有的JAVA类都会具有这个两个方法,为什么会被这样设计呢?我们可以认为所有的对象默认都具有一个锁,虽然我们看不到,也没有办法直接操作,但它是存在的。
wait()方法表示:当缓冲区已满或空时,生产者或消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让另一个线程开始执行;
notify()方法表示:当生产者或消费者对缓冲区放入或取出一个产品时,向另一个线程发出可执行通知,同时放弃锁,使自己处于等待状态。
下面是一个例子代码:
import java.util.LinkedList;
public class Sycn1{
private LinkedList<Object> myList =new LinkedList<Object>();
private int MAX = 10;
public Sycn1(){
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn1 s1 = new Sycn1();
s1.start();
}
class Producer extends Thread{
public void run(){
while(true){
synchronized(myList){
try{
while(myList.size() == MAX){
System.out.println("warning: it's full!");
myList.wait();
}
Object o = new Object();
if(myList.add(o)){
System.out.println("Producer: " + o);
myList.notify();
}
}catch(InterruptedException ie){
System.out.println("producer is interrupted!");
}
}
}
}
}
class Consumer extends Thread{
public void run(){
while(true){
synchronized(myList){
try{
while(myList.size() == 0){
System.out.println("warning: it's empty!");
myList.wait();
}
Object o = myList.removeLast();
System.out.println("Consumer: " + o);
myList.notify();
}catch(InterruptedException ie){
System.out.println("consumer is interrupted!");
}
}
}
}
}
}
2. 方法await()/signal()
在JDK5.0以后,JAVA提供了新的更加健壮的线程处理机制,包括了同步、锁定、线程池等等,它们可以实现更小粒度上的控制。await()和signal()就是其中用来做同步的两种方法,它们的功能基本上和wait()/notify()相同,完全可以取代它们,但是它们和新引入的锁定机制Lock直接挂钩,具有更大的灵活性。
下面是一个例子代码:
import java.util.LinkedList;
import java.util.concurrent.locks.*;
public class Sycn2{
private LinkedList<Object> myList = new LinkedList<Object>();
private int MAX = 10;
private final Lock lock = new ReentrantLock();
private final Condition full = lock.newCondition();
private final Condition empty = lock.newCondition();
public Sycn2(){
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn2 s2 = new Sycn2();
s2.start();
}
class Producer extends Thread{
public void run(){
while(true){
lock.lock();
try{
while(myList.size() == MAX){
System.out.println("warning: it's full!");
full.await();
}
Object o = new Object();
if(myList.add(o)){
System.out.println("Producer: " + o);
empty.signal();
}
}catch(InterruptedException ie){
System.out.println("producer is interrupted!");
}finally{
lock.unlock();
}
}
}
}
class Consumer extends Thread{
public void run(){
while(true){
lock.lock();
try{
while(myList.size() == 0){
System.out.println("warning: it's empty!");
empty.await();
}
Object o = myList.removeLast();
System.out.println("Consumer: " + o);
full.signal();
}catch(InterruptedException ie){
System.out.println("consumer is interrupted!");
}finally{
lock.unlock();
}
}
}
}
}
3. 阻塞队列方法BlockingQueue
BlockingQueue也是JDK5.0的一部分,它是一个已经在内部实现了同步的队列,实现方式采用的是我们的第2种await()/signal()方法。它可以在生成对象时指定容量大小。
它用于阻塞操作的是put()和take()方法。
put()方法类似于我们上面的生产者线程,容量最大时,自动阻塞。
take()方法类似于我们上面的消费者线程,容量为0时,自动阻塞。
下面是一个例子代码:
import java.util.concurrent.*;
public class Sycn3{
private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10);
private int MAX = 10;
public Sycn3(){
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn3 s3 = new Sycn3();
s3.start();
}
class Producer extends Thread{
public void run(){
while(true){
//synchronized(this){
try{
if(queue.size() == MAX)
System.out.println("warning: it's full!");
Object o = new Object();
queue.put(o);
System.out.println("Producer: " + o);
}catch(InterruptedException e){
System.out.println("producer is interrupted!");
}
//}
}
}
}
class Consumer extends Thread{
public void run(){
while(true){
//synchronized(this){
try{
if(queue.size() == 0)
System.out.println("warning: it's empty!");
Object o = queue.take();
System.out.println("Consumer: " + o);
}catch(InterruptedException e){
System.out.println("producer is interrupted!");
}
//}
}
}
}
}
你发现这个例子中的问题了吗?
如果没有,我建议你运行一下这段代码,仔细观察它的输出,是不是有下面这个样子的?为什么会这样呢?
…
warning: it's full!
Producer: java.lang.object@4526e2a
…
你可能会说这是因为put()和System.out.println()之间没有同步造成的,我也这样认为,我也这样认为,但是你把run()中的synchronized前面的注释去掉,重新编译运行,有改观吗?没有。为什么?
这是因为,当缓冲区已满,生产者在put()操作时,put()内部调用了await()方法,放弃了线程的执行,然后消费者线程执行,调用take()方法,take()内部调用了signal()方法,通知生产者线程可以执行,致使在消费者的println()还没运行的情况下生产者的println()先被执行,所以有了上面的输出。run()中的synchronized其实并没有起什么作用。
对于BlockingQueue大家可以放心使用,这可不是它的问题,只是在它和别的对象之间的同步有问题。
对于这种多重嵌套同步的问题,以后再谈吧,欢迎大家讨论啊!
4. 管道方法PipedInputStream/PipedOutputStream
这个类位于java.io包中,是解决同步问题的最简单的办法,一个线程将数据写入管道,另一个线程从管道读取数据,这样便构成了一种生产者/消费者的缓冲区编程模式。
下面是一个例子代码,在这个代码我没有使用Object对象,而是简单的读写字节值,这是因为PipedInputStream/PipedOutputStream不允许传输对象,这是JAVA本身的一个bug,具体的大家可以看sun的解释:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4131126
import java.io.*;
public class Sycn4{
private PipedOutputStream pos;
private PipedInputStream pis;
//private ObjectOutputStream oos;
//private ObjectInputStream ois;
public Sycn4(){
try{
pos = new PipedOutputStream();
pis = new PipedInputStream(pos);
//oos = new ObjectOutputStream(pos);
//ois = new ObjectInputStream(pis);
}catch(IOException e){
System.out.println(e);
}
}
public void start(){
new Producer().start();
new Consumer().start();
}
public static void main(String[] args) throws Exception{
Sycn4 s4 = new Sycn4();
s4.start();
}
class Producer extends Thread{
public void run() {
try{
while(true){
int b = (int) (Math.random() * 255);
System.out.println("Producer: a byte, the value is " + b);
pos.write(b);
pos.flush();
//Object o = new MyObject();
//oos.writeObject(o);
//oos.flush();
//System.out.println("Producer: " + o);
}
}catch(Exception e){
//System.out.println(e);
e.printStackTrace();
}finally{
try{
pos.close();
pis.close();
//oos.close();
//ois.close();
}catch(IOException e){
System.out.println(e);
}
}
}
}
class Consumer extends Thread{
public void run(){
try{
while(true){
int b = pis.read();
System.out.println("Consumer: a byte, the value is " + String.valueOf(b));
//Object o = ois.readObject();
//if(o != null)
//System.out.println("Consumer: " + o);
}
}catch(Exception e){
//System.out.println(e);
e.printStackTrace();
}finally{
try{
pos.close();
pis.close();
//oos.close();
//ois.close();
}catch(IOException e){
System.out.println(e);
}
}
}
}
//class MyObject implements Serializable {
//}
}
发表评论
-
Maven2
2012-02-27 20:30 941一.背景 Maven2 的基本原理很简单,采用远程仓库和本地 ... -
Java 路径详解
2011-10-28 13:19 714一 相对路径的获得 ... -
JAVA工程路径
2011-10-28 13:17 0一 相对路径的获得 ... -
(转)Thread 介绍(一)
2011-10-27 13:28 911引用 线程(引用自Java API doc): 引用 线程 是 ... -
Class.getResourceAsStream 和 ClassLoader.getResourceAsStream区别
2011-10-25 10:00 526两个都可以用于从 classpath 里面进行资源读取, c ... -
FileChannel 类(转)
2011-10-25 09:23 1003java.nio.channels.FileChannel 用 ... -
61条面向对象的法则
2011-10-24 09:16 612(1)所有数据都应该隐藏在所在的类的内部。 (2)类的使用者 ... -
J2SE 5.0新特性
2011-10-21 13:18 565J2SE(TM) 5.0引入了很多激 ... -
java(Web)中相对路径,绝对路径问题总结
2011-10-20 16:22 7971.基本概念的理解 ... -
(转)国内外Java学习论坛汇总
2011-10-13 10:11 1115引用 国外Java论坛: www.sun.com 不用多说 ... -
setTimeout和setInterval
2011-09-30 13:27 774引用 Java可发者熟悉对 ... -
ThreadPoolExecutor
2011-09-15 13:44 721一、简介 线程池类为 ... -
(转载)Java多线程sleep(),join(),interrupt(),wait(),notify()
2011-09-15 13:43 823关于Java多线程知识可以看看《Thinking in Jav ... -
java-thread-1(转载)
2011-09-14 16:35 724先从线程的创建说起.线程的创建一共有两种形式: ------- ... -
数据库连接池技术中dbcp、c3p0、jndi
2011-09-14 09:49 750不管通过何种持久化技术,都必须通过数据连接访问数据库,在Spr ... -
C3P0连接池配置(转载)
2011-09-13 17:28 537<c3p0-config> <defaul ... -
几种常见数据库连接池的使用比较(转载)
2011-09-13 17:11 917[color=blue][/color][align=l ...
相关推荐
课程大作业啊,绝对真实,用多线程技术实现的,对初学多线程技术的童鞋绝对有帮助,亲,还不下载等什么呢
设计目的:通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制。说明:有界缓冲区内设有20 个存储单元,放入/取出的数据项设定为1‐20 这20 个整型数。设计要求:1)每个生产者和消费者对有界缓冲区...
操作系统实验二:生产者——消费者问题 ...3. 两种环境下,生产者和消费者均作为独立线程,并通过empty、full、mutex三个信号量实现对缓冲进行插入与删除。 4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。
在生产者---消费者问题中应注意(信号量名称以多个生产者和多个消费者中的为例):首先,在每个程序中用于互斥的wait(mutex)和signal(mutex)必须成对出现;其次,对资源信号量empty和full的wait和signal操作,同样...
该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗...
用c#做的一个生产者消费者模型,可以自己选择生产者消费者以及缓冲区大小,可视化操作,课程设计必备~
在Linux下完整C语言实现生产者消费者问题的代码。其中涉及信号量、多线程、GCC编译、PV操作等基础知识。Linux下通过gcc - o yy xxx.c -pthread,再通过./yy即可运行。
C#的多线程机制探索 doc 一.多线程的概念 二.操纵一个线程 三.线程的同步和通讯——生产者和消费者 四、线程池和定时器——多线程的自动管理
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和...
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和...
以生产者消费者模型为基础,在Windows环境下创建一个控制台进程,在该进程中创建读者写者线程模拟生产者和消费者。写者线程写入数据,然后将数据放置在一个空缓冲区中供读者线程读取。读者线程从缓冲区中获得数据,...
重命名 实验三多:线程同步与协作:生产者与消费者 为 实验三:多线程同步与协作:生产者与消费者 实验九:使用jdbc存取大文本 add 实验九:使用jdbc存取大文本. 实验二:多线程打字游戏 add 实验二:多线程...
用同步对象、自定义计数信号量等四种方法实现生产者消费者共享有限缓冲区问题Vc++源代码。问题描述:一些生产者线程各自找出自己要搜索的范围内的素数,并放到一个有限缓冲区——数组中,另一些消费者线程线程将数组...
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。 在 Java 中可以用 wait、notify ...例如,在生产者消费者模
在char01包里放置Java多线程基本知识的代码。内容如下: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 在char02包里放置了Java对变量和对象... 多对多 生产者/消费者
年 级: 2010级 小组成员: A B 指导教师: 时 间: 地 点: 2012年 5 月 摘要 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的...
本例将模仿经典的线程同步互斥例子——生产者和消费者问题,来演示 java 强大的多线程机制。生产者和消费者共享一个数据,当数据为0 时,消费者不可访问,生产者可访问数据,每次访问数据加1;当数据到达100 时,...
老师提高了一般生产者消费者的要求——要求有两个“仓库”作中间的搬运者。运用java多线程,和信号量的机制实现程序。希望和大家共同学习!!
操作形同实验——进程同步和互斥 (1) 通过编写程序实现进程同步和...(2) 了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。 (3) 学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。
操作系统大作业,算法集锦:生产者与消费者——多线程与同步问题;多级反馈队列调度算法;银行家算法