线程经典代码三,(循环缓冲区,生产者/消费者关系)

1,生产者和消费者(循环缓冲区)该程序实现为一个窗口应用程序 

        循环缓冲区好处是:使共享资源的线程的等待时间减到最小,并使他们的平均操作速度相同。
        注意:循环缓冲区不适合于生产者和消费者持续以不同的速度进行操作的情况。
        缓冲区太小,这样会使线程等待更多的时间。
        缓冲区太大,这样会浪费内存。

2,即使使用了循环缓冲区,生产者也可能会填满该缓冲区,这将迫使生产者一直处于
 等待状态,除非消费者消费了一个值,空出缓冲区的一个单元。
 类似地,如果缓冲区任何时刻都是空的,则消费者线程一直处于等待状态,除非生
 产者产生了另一个值,使用循环缓冲区的关键在于优化该缓冲区的大小,使线程等
 待时间减到最小。

 

 

// ********************接口方法
public   interface  Buffer  {

    
public void set(int value);
    
public int get();
}




// ********************生产者
import  javax.swing.JTextArea;
import  javax.swing.SwingUtilities;

public   class  Product  extends  Thread  {

    
private Buffer sharedLocation;
    
private JTextArea outputArea;
    
    
//构造函数
    public Product(Buffer shared,JTextArea output)
    
{
        
super("Product");
        sharedLocation 
= shared;
        outputArea 
= output;
    }

    
    
public void run()
    
{
        
for(int i=11;i<=20;i++)
        
{
            
try{
                Thread.sleep((
int)(Math.random() * 3000));
                sharedLocation.set(i);
            }
catch(InterruptedException e){
                e.printStackTrace();
            }

            
        }

        String name 
= getName();
        
        SwingUtilities.invokeLater(
new RunnableOutput(outputArea," " +
                name 
+"done producing. " + name + "terminated. "));
    }

}




// ********************消费者
import  javax.swing.JTextArea;
import  javax.swing.SwingUtilities;

public   class  Consumer  extends  Thread {

    
private Buffer sharedLocation;
    
private JTextArea outputArea;
    
    
//构造函数
    public Consumer(Buffer shared,JTextArea output)
    
{
        
super("Consumer");
        sharedLocation 
= shared;
        outputArea 
= output;
    }

    
     
public void run()
        
{
            
int sum=0;
            
for(int i=1;i<=4;i++)
            
{
                
try{
                    Thread.sleep((
int)(Math.random() * 3001));
                    sum 
+= sharedLocation.get();
                 }
catch(InterruptedException e){
                    e.printStackTrace();
                }

            }


            String name 
= getName();
            
//involeLater是SwingUtilites的静态方法,它指定GUI处理语句稍后在事件调度线程中执行,并以实现Runnable接口的对象为参数。
            SwingUtilities.invokeLater(new RunnableOutput (outputArea," Total" + name +"consumed:"+sum+". "
                    
+name+"terminated. "));
            
            
        }

    
}




// ********************RunnableOutput方法
// 此方法传给SwingUtilities类的invokeLater,以更新事件调度线程中的GUI。
// 每个实现Runnable接口的类必须让照以下形式声明run方法

/*    每个RunnableOutput对象接受一个显示输出的JTextArea引用和一个字符串,
    该字符代表显示的消息。
    RunnableOutput类的run方法将该消息添加到JTextArea中。该程序调用invokeLater
    方法时,该GUI组件的更新操作将在事件调度线程中排队等待执行。
    然后作为事件调度线程的一部分,将调用RunnableOutput类的run方法,以执行输出操作。
*/



import  javax.swing. * ;

public   class  RunnableOutput  implements  Runnable {

    
private JTextArea outputArea;
    
private String messageToAppend;
    
    
public RunnableOutput(JTextArea output,String message){
        outputArea 
= output;
        messageToAppend 
= message;
    }

    
    
public void run() {
        
        outputArea.append(messageToAppend);
    }


}






// ********************此方法主要是 监视对共享数据组的访问
import  javax.swing. * ;

public   class  CircularBuffer  implements  Buffer {
    
    
private int buffers[] = {-1,-1,-1};
    
private int occupiedBufferCount = 0;
    
private int readLocation = 0;
    
private int writeLocation = 0;
    
private JTextArea outputArea;
    
    
public CircularBuffer(JTextArea output)
    
{
        outputArea 
= output;
    }

    
    
public int get() {

        String name 
= Thread.currentThread().getName();
        
        
while(occupiedBufferCount == 0){
            
            
try {
                SwingUtilities.invokeLater(
new RunnableOutput (outputArea,
                        
" All buffers empty." + name + "waits" ));
                wait();
            }
 catch (InterruptedException e) {
                
// TODO 自动生成 catch 块
                e.printStackTrace();
            }

        }

        
        
int readValue = buffers [ readLocation ];
        SwingUtilities.invokeLater(
new RunnableOutput (outputArea,
                
" " + name + "reads" + readValue + " " ));
        
        
--occupiedBufferCount;
        
        readLocation 
= (readLocation + 1% buffers.length;
        
        SwingUtilities.invokeLater(
new RunnableOutput (outputArea,createStateOutput()));
        notify();
        
return readValue;
    }


    
public synchronized void set(int value) {

        String name 
= Thread.currentThread().getName();
        
        
while(occupiedBufferCount == buffers.length){
            
try {
                SwingUtilities.invokeLater(
new RunnableOutput (outputArea,
                        
" All buffers full." +name+"waits"));
                wait();
            }
 catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        
        buffers[writeLocation] 
= value;
        
        SwingUtilities.invokeLater(
new RunnableOutput (outputArea,
                
" " + name + " write " + buffers[ writeLocation ] + " "));
        
        
++occupiedBufferCount;
        
        writeLocation 
= (writeLocation + 1% buffers.length;
        
        SwingUtilities.invokeLater(
new RunnableOutput (outputArea,createStateOutput() ));
        notify();
    }


    
public String createStateOutput() {
        
        String output 
= "(buffers occupied: " +occupiedBufferCount + ") buffers: ";
        
        
for(int i=0;i<buffers.length;i++)
            output 
+= " " + buffers[i] + " ";
        output 
+="      ";
        
        
for(int i=0;i<buffers.length;i++)
            output 
+= "--------- ";
        output 
+="      ";
        
        
for(int i=0;i<buffers.length;i++)
            
if(i==writeLocation && writeLocation == readLocation)
                output 
+= " WR ";
            
else if( i == writeLocation )
                output 
+= " W ";
            
else if( i == readLocation )
                output 
+= " R ";
            
else
                output 
+= "      ";
        output 
+= " ";
        
        
return output;
    }


}





// ********************测试类
import  java.awt.Font;
import  javax.swing.JFrame;
import  javax.swing.JScrollPane;
import  javax.swing.JTextArea;
import  javax.swing.SwingUtilities;

public   class  CircularBufferTest  extends  JFrame {

    JTextArea outputArea;
    
    
public CircularBufferTest()
    
{
        
super("Demonstrating Thread Synchronizaton");
        
        outputArea 
= new JTextArea(20,30);
        outputArea.setFont(
new Font("Monospaced",Font.PLAIN,12));
        getContentPane().add(
new JScrollPane(outputArea));
        
        setSize(
310,500);
        setVisible(
true);
        
        CircularBuffer sharedLocation 
= new CircularBuffer(outputArea);
        
        SwingUtilities.invokeLater ( 
new RunnableOutput( outputArea,sharedLocation.createStateOutput() ) );
        
        Product product 
= new Product( sharedLocation, outputArea);
        Consumer consumer 
= new Consumer( sharedLocation, outputArea);
        
        product.start();
        consumer.start();
    }

    
    
public static void main(String args[])
    
{
        CircularBufferTest application 
= new CircularBufferTest();
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值