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);
}
}
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);
}
}