多线程管理
- 线程类
–通过继承Thread或实现Runable
– 通过start方法,调用run方法,run方法工作
– 线程run结束后,线程退出 - 粗粒度: 子线程与子线程之间、和main线程之间缺乏同步
- 细粒度:线程之间有同步协作
– 等待
– 通知/唤醒
– 终止- 等待:等A线程执行到某一个地方的时候,B线程告A线程,让A等待一会,等A到了,在往下一起走
- 通知/唤醒: A到了,A告诉B,我到了,可以走了
- 线程状态
– NEW 刚创建(new)
– RUNNABLE 就绪态(start)
– RUNNING 运行中(run)
– BLOCK 阻塞(sleep)
– TERMINATED 结束
- Thread的部分API已经废弃
– 暂停和恢复spspend/resume (这些方法很危险,已经废弃,不建议使用)
– 消亡 stop/destroy (这些方法很危险,已经废弃,不建议使用) - 线程阻塞/和唤醒
– sleep,时间一到,自己会醒来
– wait/notify/notifyAll 等待,需要别人来唤醒
– join 等待另外一个线程结束
– interrupt 向另外一个线程发送中断信号,该线程收到信号,会触发InterruptedException(可解除阻塞),并进行下一步处理- wait: 休眠状态,等别的线程调用notify或者notifyAll的时候,可以醒来。一个等待(wait)的线程是需要其他线程去唤醒的,如果没有其他线程去唤醒它,那这个线程就一直等待,一直处于休眠状态
生产者/消费者示例:
经典生成者与消费者问题
生产者不断的往仓库中存放产品,消费者从仓库中消费产品。
其中生产者和消费者都可以有若干个。
仓库规则:容量有限,库满时不能存放,库空时不能取产品。
源码示例:
//产品
public class Product {
private Integer id;
private String name;
}
package product;
/**
* @ClassName:Storage
* @Description:仓库类
* @author: Torey
*/
public class Storage {
//仓库容量
public Storage(Integer volume) {
this.products = new Product[volume];
this.volume=volume;
}
//仓库容量
private Integer volume;
public Integer getVolume() {
return volume;
}
public void setVolume(Integer volume) {
this.volume = volume;
}
//仓库容量
private Product[] products ;
private int top = 0;
//生产者向仓库中放入产品
public synchronized void push(Product product){
while (top == products.length) {
try {
System.out.println("product wait");
wait();//仓库已满,等待
}catch (Exception ex){
ex.printStackTrace();
}
}
//把产品放入仓库
products[top++]=product;
System.out.println("producer notifyAll"+Thread.currentThread().getName() + "生产了产品:"+product);
notifyAll();//唤醒等待线程
}
//消费者从仓库中取出产品
public synchronized Product pop() {
while (top == 0) {
try{
System.out.println("empty! consumer wait");
wait();}catch (Exception ex){
ex.printStackTrace();
}
}
//从仓库中取产品
--top;
Product p = new Product(products[top].getId(), products[top].getName());
products[top]=null;
System.out.println("comsumer notifyAll "+Thread.currentThread().getName() + " 消费了产品:" + p);
notifyAll(); //唤醒等待的线程
return p;
}
}
package product;
/**
* @ClassName:Consumer
* @Description:消费者
* @author: Torey
*/
public class Consumer implements Runnable {
private Storage storage;
/**
*
* @param storage 仓库
* @param interval 多久消费一个
*/
public Consumer(Storage storage,Integer interval) {
this.storage = storage;
this.integer=interval*1000;
}
private Integer integer;
@Override
public void run() {
int i=0;
while (true){
try {
i++;
storage.pop();
Thread.sleep(integer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package product;
import java.util.Random;
/**
* @ClassName:Producer
* @Description:生产者
* @author: Torey
*/
public class Producer implements Runnable {
private Storage storage;
/**
*
* @param storage 仓库
* @param integer 多久生产一个
*/
public Producer(Storage storage,Integer integer) {
this.storage = storage;
this.integer=integer*1000;
}
private Integer integer;
@Override
public void run() {
int i=0;
Random r = new Random();
while (true){
i++;
Product product = new Product(i, "电话" + r.nextInt(100));
try {
Thread.sleep(integer);
storage.push(product);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package product;
/**
* @ClassName:ProductTest
* @Description:
* 经典生成者与消费者问题
* 生产者不断的往仓库中存放产品,消费者从仓库中消费产品。
* 其中生产者和消费者都可以有若干个。
* 仓库规则:容量有限,库满时不能存放,库空时不能取产品。
* @author: Torey
*/
public class ProductTest {
public static void main(String[] args) throws InterruptedException {
//仓库容量为 5个
Storage storage = new Storage(5);
//每5秒钟消费一次
new Thread(new Consumer(storage,5),"消费者1").start();
//每秒生产一个
new Thread(new Producer(storage,1),"生产者2").start();
}
}