多執行緒:通過兩個不安全例子學習同步鎖,synchronized同步方法/同步塊,JUC, lock鎖
阿新 • • 發佈:2020-09-17
模擬搶購火車票
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(); } } } }