多线程:通过两个不安全例子学习同步锁,synchronized同步方法/同步块,JUC, lock锁
模拟抢购火车票
package com.cl.syn; //不安全买票,会出现多人买同一张票,导致票数出现负数 //解决,synchronized,同步方法,让多个线程之间做到排队等待 //缺点:若将一个大的方法申明synchronized将会影响效率 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket station = new BuyTicket(); new Thread(station,"帅气的我").start(); new Thread(station,"老黄牛").start(); new Thread(station,"小黄").start(); } } class BuyTicket implements Runnable{ //票 private int ticketNums=10; boolean flag=true;//外部停止方式 @Override public void run() { //买票 while (flag){ buy(); } } private synchronized void buy(){ //判断是否有票 if (ticketNums<=0){ flag=false; return; } //模拟延时,放大存在问题 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //那个进程抢到票 System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--); } }
模拟多人在统一账户取钱
package com.cl.syn; //不安全的取钱 //模拟两个人去银行取钱,账户 //解决: //synchronized默认同步的是this,本身 //因此要用同步块, public class UnsafeBank { public static void main(String[] args) { //账户 Account account = new Account(1000, "结婚基金"); Drawing you=new Drawing(account,50,"你"); Drawing friend=new Drawing(account,100,"friend"); you.start(); friend.start(); } } //账户 class Account{ int money;//余额 String name;//卡名 public Account(int money,String name){ this.money=money; this.name=name; } } //银行 class Drawing extends Thread{ Account account;//账户 int drawingMoney;//取了多少钱 int nowMoney;//手里有多少钱 public Drawing(Account account,int drawingMoney,String name){ super(name); this.account=account; this.drawingMoney=drawingMoney; } //取钱 @Override public void run() { //锁的对象就是变化的量,需要增删改查的对象 synchronized (account){ //判断有没有钱 if(account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"钱不够,取不了"); return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //卡内余额 account.money-=drawingMoney; //手里的钱 nowMoney+=drawingMoney; System.out.println(account.name+"余额:"+account.money); System.out.println(this.getName()+"手里的钱:"+nowMoney); } } }
测试JUC安全类型的集合
package com.cl.syn; //util.concurrent,并发包 import java.util.concurrent.CopyOnWriteArrayList; //测试JUC安全类型的集合 public class TestJUC { public static void main(String[] args) { CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
了解lock锁
package com.cl.syn; import java.util.concurrent.locks.ReentrantLock; //测试lock锁,加锁:lock.lock() // 解锁:lock.unlock(); public class TestLock { public static void main(String[] args) { TestLock2 testLock2 = new TestLock2(); new Thread(testLock2).start(); new Thread(testLock2).start(); new Thread(testLock2).start(); } } class TestLock2 implements Runnable{ int ticketNums=10; //定义lock锁 private final ReentrantLock lock=new ReentrantLock(); @Override public void run() { while (true){ try { lock.lock();//加锁 if (ticketNums>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNums--); }else { break; } }finally { //解锁 lock.unlock(); } } } }