多线程编写模板套路(lock版)
1) 在高内聚低耦合的前提下,线程操作资源类
资源类
class Ticket{ private int num = 30; public void sale(){ System.out.println("sale"); } }
主进程
public static void main(String[] args) { //创建资源类 Ticket ticket = new Ticket(); //线程操作资源类 new Thread(()->{ ticket.sale(); },"A").start(); }
2) 判断/干活/通知
资源类
class ShareDate{ private int numble = 0; private Lock lock = new ReentrantLock(); private Condition[] condition = { lock.newCondition(), lock.newCondition(), lock.newCondition() }; public void printByNum(int num){ lock.lock(); try{ //判断 if(numble != num) { condition[num].await(); } //干活 for (int i = 0; i < 2 * (num+1); i++){ System.out.println(Thread.currentThread().getName() + "\t" + (i+1)); } //通知 numble = ++numble % 3; condition[numble].signal(); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }
主进程
public static void main(String[] args) { //线程控制资源类 ShareDate shareDate = new ShareDate(); new Thread(()->{ for(int i = 0; i < 4; i++){ shareDate.printByNum(0); } },"A").start(); new Thread(()->{ for(int i = 0; i < 4; i++){ shareDate.printByNum(1); } },"B").start(); new Thread(()->{ for(int i = 0; i < 4; i++){ shareDate.printByNum(2); } },"C").start(); }
在多线程世界中,如果使用if作为判断语句,则会出现预料之外的结果:
资源类
class NumberDemo{ private int num = 0; private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); public void incr(){ lock.lock(); try{ //判断 if(num != 0){ condition1.await(); } //干活 num++; System.out.println(Thread.currentThread().getName() + "\t:\t" + num); //通知 condition2.signal(); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } public void desc(){ lock.lock(); try{ if(num != 1){ condition2.await(); } num--; System.out.println(Thread.currentThread().getName() + "\t:\t" + num); condition1.signal(); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }
主进程
public static void main(String[] args) { NumberDemo number = new NumberDemo(); new Thread(()->{ for (int i = 0; i < 10; i++){ number.incr(); } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++){ number.incr(); } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++){ number.desc(); } },"C").start(); new Thread(()->{ for (int i = 0; i < 10; i++){ number.desc(); } },"D").start(); }
结果:

出现了意料之外的结果:-1
解决方法:不使用if来判断语句,而是使用while来代替
3) 使用while防止虚假唤醒
class ShareDate{ private int numble = 0; private Lock lock = new ReentrantLock(); private Condition[] condition = { lock.newCondition(), lock.newCondition(), lock.newCondition() }; public void printByNum(int num){ lock.lock(); try{ //判断 while(numble != num) { condition[num].await(); } //干活 for (int i = 0; i < 2 * (num+1); i++){ System.out.println(Thread.currentThread().getName() + "\t" + (i+1)); } //通知 numble = ++numble % 3; condition[numble].signal(); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }

浙公网安备 33010602011771号