20.1解决线程三大问题
利用同步块进行买票
不会出现
public class Sercity_one { //不安全的买票 public static void main(String[] args) { Buy_tickets buy_tickets=new Buy_tickets(); new Thread(buy_tickets,"你").start(); new Thread(buy_tickets,"我").start(); new Thread(buy_tickets,"他").start(); } } class Buy_tickets implements Runnable{ //初始化票 private int ticket=10; boolean flag=true; @Override public void run() { while (flag){ //进行网络延迟,放大问题的发生性, try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } buy(); } } public synchronized void buy(){ //设置为同步方法.锁的是this也就是Buy_tickets if(ticket<=0){ flag=false; return; }else { //买票 System.out.println(Thread.currentThread().getName()+"买到了"+ticket--); } } }
解决银行取钱的问题
public class Sercity_two { public static void main(String[] args) { //账户初始化 account account_two=new account(100,"结婚基金"); //线程类的初始化 Bank bank=new Bank(account_two,50,"新浪"); Bank bank_one=new Bank(account_two,100,"新娘"); bank.start(); bank_one.start(); } } //账户 class account { int money; //存款 String name; //账户名字 public account(int money, String name) { this.money = money; this.name = name; } } //银行 class Bank extends Thread{ account account_one; int get_money; //取了多少钱 int now_money; //现在手上还有多少钱 //利用构造器进行 public Bank(account account_one,int get_money,String name){ super(name); this.account_one=account_one; this.get_money=get_money; } //取钱操作 public void run(){ synchronized (account_one){ //判断有没有钱 if(account_one.money-get_money<0){ System.out.println(Thread.currentThread().getName()+"余额不足,取不出"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //卡内余额 account_one.money=account_one.money-get_money; //你手上的钱 now_money=now_money+get_money; //卡内余额为: System.out.println(account_one.name+"余额为:"+account_one.money); System.out.println(Thread.currentThread().getName()+"手里的钱:"+now_money); } } }
解决集合的问题
import java.util.ArrayList; import java.util.List; public class Sercity_three { public static void main(String[] args) { List<String> list=new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
21.死锁
多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行 ,而导致两个或则多个线程都在等待对方释放资源,都停止执行的情形,某一个 同步块同时拥有"两个以上对象的锁"时,就可能会发生"死锁"的问题 (我想要车,你想要枪。于是一直等待对方玩完)
死锁: 一直处于锁死的状态
public class Dead_lock { public static void main(String[] args) { Markup markup=new Markup(1,"灰菇凉"); Markup markup1=new Markup(0,"白雪公主"); markup.start(); markup1.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } class Markup extends Thread{ static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice; String person_name; Markup(int choice,String person_name){ this.choice=choice; this.person_name=person_name; } public void run(){ try { markup_two(); } catch (Exception e) { e.printStackTrace(); } } //化妆 private void markup_two() throws Exception{ if (choice==0){ synchronized (lipstick){ //获得口红的锁 System.out.println(Thread.currentThread().getName()+"获得了口红锁"); Thread.sleep(1000); synchronized (mirror){ //一秒钟后想要镜子 System.out.println(Thread.currentThread().getName()+"获得了镜子锁"); } } }else { synchronized (mirror){ //获得口红的锁 System.out.println(Thread.currentThread().getName()+"获得了镜子锁"); Thread.sleep(2000); synchronized (lipstick){ //一秒钟后想要镜子 System.out.println(Thread.currentThread().getName()+"获得了想要镜子锁"); } } } } }
非死锁: 都能够拿到需要的东西
public class Dead_lock { public static void main(String[] args) { Markup markup=new Markup(1,"灰菇凉"); Markup markup1=new Markup(0,"白雪公主"); markup.start(); markup1.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } class Markup extends Thread{ static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice; String person_name; Markup(int choice,String person_name){ this.choice=choice; this.person_name=person_name; } public void run(){ try { markup_two(); } catch (Exception e) { e.printStackTrace(); } } //化妆 private void markup_two() throws Exception{ if (choice==0){ synchronized (lipstick){ //获得口红的锁 System.out.println(Thread.currentThread().getName()+"获得了口红锁"); Thread.sleep(1000); } synchronized (mirror){ //一秒钟后想要镜子 System.out.println(Thread.currentThread().getName()+"获得了镜子锁"); } }else { synchronized (mirror){ //获得口红的锁 System.out.println(Thread.currentThread().getName()+"获得了镜子锁"); Thread.sleep(2000); }synchronized (lipstick){ //一秒钟后想要镜子 System.out.println(Thread.currentThread().getName()+"获得了想要镜子锁"); } } } }
死锁避免的方法: 产生死锁的四个必要条件: 1.互斥条件:一个资源每次只能被一个进程使用 2.请求与保持条件:一个进程因请求资源而阻塞时,对以获得的资源保持不放 3.不剥夺条件:进程已获得的资源,在未使用之前,不能强行剥夺 4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
22.lock(锁)
ReentrantLock 类 加锁: lock(); 取锁: unlock(); 加锁和取锁要写在 try{}finally{}中
import java.util.concurrent.locks.ReentrantLock; public class Test_lock { public static void main(String[] args) { test2 test_one=new test2(); new Thread(test_one).start(); new Thread(test_one).start(); new Thread(test_one).start(); } } class test2 implements Runnable{ int ticket=10; //定义锁 private final ReentrantLock reentrantLock=new ReentrantLock(); @Override public void run() { while (true){ try { reentrantLock.lock(); //加锁 if(ticket>0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticket--); }else { break; } } finally { reentrantLock.unlock(); //解锁 } } } }
(六)、线程协作
生产者和消费者模式:
1.这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和 消费者之间相互依赖,互为条件。 (1).对于生产者:没有产品,通知消费者等待,有产品,马上通知消费者消费 (2).对于消费者:在消费后,通知消费者已经结束消费,需要生产新的产品进行 消费 (3).在生产者和消费者问题中 synchron是不够的 2.解决线程之间通信问题的方法: (1). wait() 表示线程一直等待,直到其他线程通知,与sleep()不同,会释放锁 (2).wait(long timeout) 指定等待的毫秒数 (3).notify() 唤醒一个等待状态的线程 (4).notifyAll() 唤醒同一个对象上所调用wait()方法的线程,优先级别高的线程 优先调度