一个多线程小程序

今天看见一个多线程问题,心里痒痒,就做了做,然后就有了这么一个小程序。

问题在这里:[url]http://www.iteye.com/problems/46763[/url]

有三方:厂家,电脑城,顾客
厂家2个,一个生产主板,一个生产显卡。
顾客有2个,他们各自不断购买主板和显卡。
电脑城有一个,卖显卡和主板。

货品类,方便调试:

public class Product {
private String name;
private int serial;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getSerial() {
return serial;
}

public void setSerial(int serial) {
this.serial = serial;
}
}


货品供需管理类,多线程调度的核心:
import java.util.ArrayDeque;

public class StockManager {
private final Object producerLock = new Object();
private final Object consumerLock = new Object();
private final int MAX_SIZE = 10;

private final ArrayDeque<Product> queue = new ArrayDeque<Product>();

public void stock(Product p) throws InterruptedException {
synchronized (producerLock) {
if (queue.size() >= MAX_SIZE) {
producerLock.wait();
}
}
synchronized (queue) {
queue.add(p);
}
synchronized (consumerLock) {
consumerLock.notify();
}
}

public synchronized Product purchase() throws InterruptedException {
synchronized (consumerLock) {
if (queue.size() <= 0) {
consumerLock.wait();
}
}
Product product = null;
synchronized (queue) {
product = queue.remove();
}
synchronized (producerLock) {
producerLock.notify();
}
return product;
}
}


厂商类,可以生产产品,另有一个run,用于实现具体的生产过程,以调节测试时的供求关系:
import java.util.logging.Logger;

public class Producer implements Runnable{
private static final Logger log = Logger.getLogger(Producer.class.getName());

private String productName = null;
private int serial = 0;
private StockManager stockManager;

public void setProductName(String productName) {
this.productName = productName;
}

public void setStockManager(StockManager stockManager) {
this.stockManager = stockManager;
}

public Product produce() {
final Product p = new Product();
p.setName(productName);
p.setSerial(++serial);
return p;
}

@Override
public void run() {
try {
for( int i = 0; i < 20; i++) {
deliver();
}
Thread.sleep(30 * 1000);
while (true) {
deliver();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private void deliver() throws InterruptedException {
final long s = System.currentTimeMillis();
final Product product = produce();
stockManager.stock(product);
final long time = System.currentTimeMillis() - s;
if (time > 10) {
log.info(product.getName() + ", No. " +
product.getSerial() + " took " +
time + " milli seconds to finish." );
}
}
}


客户类,比较简单,外加调试信息:
import java.util.logging.Logger;

public class Consumer implements Runnable {
private static final Logger log = Logger.getLogger(Consumer.class.getName());

private String name;
private StockManager[] stockManagers;

public void setName(String name) {
this.name = name;
}

public void setStockManagers(StockManager[] stockManagers) {
this.stockManagers = stockManagers;
}

@Override
public void run() {
for (int i = 0; i < 50; i++) {
final double v = Math.random() * stockManagers.length;
final int k = (int) Math.floor(v);
try {
final long s = System.currentTimeMillis();
final Product product = stockManagers[k].purchase();
final long time = System.currentTimeMillis() - s;
String l = "";
if (time > 10) {
l += "after " + time + " milli seconds of waiting, ";
}
l += (name + " bought product " + product.getName()
+ ", serial No. " + product.getSerial());
log.info(l);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}


程序入口,初始化上述各类,启动相应线程:
public class Mall {
public static void main(String[] args) {
final StockManager mb = new StockManager();
final Producer pmb = new Producer();
pmb.setProductName("Motherboard");
pmb.setStockManager(mb);

final StockManager vd = new StockManager();
final Producer pvd = new Producer();
pvd.setProductName("Video Card");
pvd.setStockManager(vd);

final StockManager[] stockManagers = new StockManager[2];
stockManagers[0] = mb;
stockManagers[1] = vd;

final Consumer c1 = new Consumer();
c1.setName("C1");
c1.setStockManagers(stockManagers);

final Consumer c2 = new Consumer();
c2.setName("C2");
c2.setStockManagers(stockManagers);

final Thread tc1 = new Thread(c1);
tc1.start();
final Thread tc2 = new Thread(c2);
tc2.start();

try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

new Thread(pmb).start();
new Thread(pvd).start();

try {
tc1.join();
tc2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

// kill system after consumer done shopping
System.exit(0);
}
}


感觉StockManager还是有些问题,但是又说不清楚。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用Java多线程实现文件复制的示例程序: ```java import java.io.*; public class FileCopyThread extends Thread { private File sourceFile; private File targetFile; public FileCopyThread(File sourceFile, File targetFile) { this.sourceFile = sourceFile; this.targetFile = targetFile; } public void run() { try { FileInputStream in = new FileInputStream(sourceFile); FileOutputStream out = new FileOutputStream(targetFile); byte[] buffer = new byte[4096]; // 缓冲区大小为4KB int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { File source = new File("source.txt"); File target = new File("target.txt"); int threadCount = 4; // 创建4个线程 long fileSize = source.length(); long blockSize = fileSize / threadCount; for (int i = 0; i < threadCount; i++) { long start = i * blockSize; long end = (i == threadCount - 1) ? fileSize : (i + 1) * blockSize; new FileCopyThread(source, target, start, end).start(); } } } ``` 该程序使用了多线程来复制文件。首先,将要复制的文件分成若干个块,每个块由一个线程处理。在 `FileCopyThread` 类的构造函数中,需要传入源文件和目标文件,以及该线程需要复制的文件块的起始和结束位置。在 `run()` 方法中,使用 `FileInputStream` 和 `FileOutputStream` 分别读取和写入文件,每次读取缓冲区大小的数据,并使用 `while` 循环重复读取和写入,直到文件复制完成。 在 `main()` 方法中,首先指定源文件和目标文件,然后指定要创建的线程数。接着,计算每个线程需要复制的文件块的起始和结束位置,并创建 `FileCopyThread` 对象,并启动该线程。 需要注意的是,该示例程序没有考虑多线程并发读写文件的问题,可能会产生竞争条件和文件损坏等问题。在实际应用中,需要使用线程同步机制来保证线程安全。同时,该程序还没有处理文件不存在等异常情况,也需要根据实际需求进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值