在基础中使用了java自带的Vector线程安全处理多线程。
这次试试用锁来进行处理
线程锁:
synchronized
使用synchronized修饰方法,这样调用这个方法的时候,这个方法会被锁定,只有当前对象使用完后才能释放让其他对象使用。
不加这个可能会多个对象同时访问这个方法,导致出现线程问题(比如出货方法,A运行到这个方法的判断是否还有货物,判断还有货物,B这时刚好也运行方法拿走了货物,A开始拿货就会报错)
public synchronized void 方法名(){...}
或者
synchronized (需要锁定的对象){ ... } 执行完代码后解锁
线程控制:
wait:
Object.wait() 让执行这个Object的线程进入等待状态,直到cpu再次分配资源(只要线程不消亡或者报错,cpu有空的时候还会自动分配资源给它执行),注意这里操作的对象是线程,多个单线程操作同一个对象,其中一个线程进入等待不影响其它线程操作这个对象。
如果在某个方法中写this.wait(); 进入等待状态的是当前操作这个对象的线程,不是当前class的对象。比如A调用了B中方法,这个方法有个this.wait(),执行到那里这个线程会断掉(不再继续往下执行),等待唤醒再继续。不影响C去调用B的方法。
所有线程都进入wait() ---》 假死状态。
防止假死需要找时机对线程进行唤醒(notify,notifyAll)
sleep:
Thread.sleep(等待时间毫秒)。 让调用方法的对象进入等待状态,等待时间到了自动醒来。
Object.notify:
唤醒当前对象的其中一个线程(cpu决定优先级,或者提前用 object.setPriority(int 优先级) 设置优先级,优先级为1-10, 10最高)
Object.notifyAll:
唤醒对象的所有线程。
生产消费者模型:
有人往仓库放,有人从仓库拿,多人同时操作同一个仓库。
主函数
packagemulti_thread;public classMultiThreadTest {public static voidmain(String[] args) {
Customer c1= new Customer("消费者1");
Customer c2= new Customer("消费者2");
Customer c3= new Customer("消费者3");
Customer c4= new Customer("消费者4");
Productor p1= new Productor("生产者1");
Productor p2= new Productor("生产者2");//生产者优先级高一些,先生产再消费
p1.setPriority(10);
p2.setPriority(10);//初始10个产品,有4个消费者每人买20次,2个生产者每人生产25个,也就是说至少会有20次买不到(消费速度 > 生产速度,还没来得及生产出来也可能买不到)
c1.start();
c2.start();
c3.start();
c4.start();
p1.start();
p2.start();
}
}
消费者
packagemulti_thread;public class Customer extends Thread{ //消费者,买取货物
privateString name;publicCustomer(String name){this.name =name;
}public voidrun(){for(int i = 0; i < 20; i++) { //假设每个消费者需要20个产品
buyGood();
}
}private voidbuyGood(){
Goods g=Goods.getInstance();
String s=g.removeGood();//多线程锁的另一种写法,在一段代码外面添加synchronized(上锁的对象){}//这样可以达到和方法上锁一样的效果//synchronized(g) {//s = g.removeGood();//}
if(s != null){
System.out.println(name+ "买走了" +s);
}else{
System.out.println(name+ "发现没货啦!");//try {//this.sleep(500);//当前Customer对象等0.1秒再买//System.out.println(name + "又开始买东西了!");//} catch (InterruptedException e) {//e.printStackTrace();//}//让某个Thread 对象(c1继承了Thread)等待111毫秒后自动醒来
}
}
}
生产者
packagemulti_thread;public class Productor extends Thread{ //生产者,增加货物
privateString name;publicProductor(String name){this.name =name;
}public voidrun(){for(int i = 0; i < 30; i++) { //假设每个生产者生产30个产品停止,刚好满足消费
productGood();
}
}private voidproductGood(){
Goods g=Goods.getInstance();
String s=g.addGood();
System.out.println(name+ "生产了" +s);
}
}
货物仓库
packagemulti_thread;importjava.util.ArrayList;public class Goods { //货物仓库,这次用String表示货物
private int num = 1; //用来区分货物
private static Goods goods = newGoods();private ArrayList goodList = new ArrayList<>(); //用String代表货物,懒得创建一个新类了。。。
{for(int i = 0; i < 20; i++){
addGood();
}
}//块,在构造方法之前自动运行,初始添加20个货物
privateGoods(){
}public staticGoods getInstance(){returngoods;
}//生产一个货物
public synchronized String addGood(){ //使用synchronized锁定方法,这样调用这个方法的时候,Goods对象会被锁定,执行完后才能释放。
goodList.add("货物" +num);
num++;return "货物" + num;//返回生产的货物名字
}//消费一个货物
public synchronizedString removeGood(){if(goodList.size() > 0) {
String s= goodList.remove(0);return s;//返回消费的货物名字;
}else{try{//wait的不是货物的线程,而是当前执行这个方法的对象所在线程(只有消费者调用这个方法)
System.out.println("有人发现到货物" + num + "的时候没货啦,等在那里不动啦");//没有添加this.notifyAll();的情况下://发现这句话运行了4遍后,4个消费者都没再买东西(因为消费者消费速度 > 生产者生产速度,还没来得及生产就卖完了),只有2个生产者还在生产。//程序卡在这里不再继续执行,称为:假死状态。//为了防止假死,在这个线程进入等待状态时,唤醒其他线程。//
//notify
this.notifyAll(); //----加上这句后,线程可以正常运行完毕。某个消费者发现没货后,过段时间还会再次尝试过购买(其他消费者发现没货了让他醒了)
this.wait();
}catch(Exception e) {
e.printStackTrace();
}return null;
}
}
}
本文介绍了如何使用Java的synchronized关键字实现线程锁,防止多线程并发问题。通过一个生产消费者模型展示了线程同步的重要性,其中包含wait(), notify()和notifyAll()的使用,以及如何防止假死状态。"
133060453,19673915,南方电网贵定供电局:无人机巡检系统与自动化实践,"['自动化', '无人机', '运维', '编程', '电力系统']

被折叠的 条评论
为什么被折叠?



