锁
线程是不安全的,随机抢占的, 线程抢到资源以后,加上锁以后,这个线程先执行结束,会自动的释放锁
用法:
1.修饰一个代码块
2.修饰一个方法
3.修饰一个静态方法
4.修饰一个类
1.修饰代码块
语法格式
一个线程访问一个对象中synchronised(this)同步代码块的时候,其他视图访问该对象的线程就会被阻塞
synchronised (this) { 代码块 }
class SynThread1 implements Runnable { @Override public void run() { // TODO Auto-generated method stub //开始锁for循环 加上锁 /** * 在同一时刻 线程会进到run方法中,发现有一个锁 * 假如SYN抢到了这个锁 syn 线程在锁的外面等待着 * SYN抢到了,就要把for循环代码执行完,锁会自动释放 * syn 才抢到,加锁了,也要把下面for循环执行完 */ synchronized (Object.class) { //加锁的这一部分,只会让一个线程先执行完。释放锁另外一个线程再进来 //this 不是线程1 也不是线程2 System.out.println(this.toString()); for (int i = 0; i < 5; i++) { System.out.println("线程的名字:" +Thread.currentThread().getName() ); } } } } public class Demo2 { public static void main(String[] args) { //开启的时候使用的是两个不同的线程类对象 Thread thread = new Thread(new SynThread1(), "SYN"); thread.start(); Thread thread1 = new Thread(new SynThread1(), "syn"); thread1.start(); //以上写法依旧是线程不安全的 乱的,为啥? } }
2.守护线程
主线程挂掉,守护线程随即也要挂掉,守护线程要依附于主线程执行
class MyThread6 implements Runnable { @Override public void run() { // TODO Auto-generated method stub System.out.println("软件更新中.........."); for (int i = 1; i < 101; i++) { System.out.println("downloding:" + i + "%"); } } } public class Demo4 { public static void main(String[] args) { Thread thread = new Thread(new MyThread6()); thread.setDaemon(true);//将线程设置为守护线程 thread.start(); //当主线程执行结束以后,守护线程即使霉运执行完也要挂掉 //更新软件 ,软件呢运行。退出软件,更新就失败了 for (int i = 1; i < 31; i++) { System.out.println("主程序在运行"); } } }
3.死锁
应用场景:并发的时候,多线程的,互不相让。
死锁一定发生在多线程之间,使用锁的目的就是线程安全的,但是物极必反。
死锁是一个状态,当两个线程互相持有对方的需要的资源的时候,却不主动释放自己的资源的时候,大致大家都用不了,线程就无法往下执行了。
知道有这个概念,然后去避免它
- 线程的几个重要的方法
wait() notify() notifyALl() 方法 都是Object 类下面的方法
- wait();
1.让线程进入到等待状态。
2.wait方法和锁一起使用。
3.需要通过对象调用。锁对象来调用
- notify():
1.唤醒线程
2.方法和锁一起使用。
3.需要通过对象调用。锁对象来调用
在一个线程中书写wait方法,此线程就会阻塞,线程处于等待状态。这个时候需要另外一个线程调用notify方法进行唤醒,让等待的线程继续执行
9.生产者消费者模式
线程之间进行通信的一种方案
package com.qfedu.c_shengchanzhe; //共享资源, 两个线程都要操作同一个商品 class Goods { private String name;//商品的名字 private double price;//商品的价格 private boolean shouldProduct;//没有商品是true。 有商品的话就是false public Goods() { } public Goods(String name, double price, boolean shouldProduct) { this.name = name; this.price = price; this.shouldProduct = shouldProduct; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public boolean isShouldProduct() { return shouldProduct; } public void setShouldProduct(boolean shouldProduct) { this.shouldProduct = shouldProduct; } //打印对象的时候是一个字符串,如果不写toString方法,打印的会是对象的内存地址 @Override public String toString() { return "Goods [name=" + name + ", price=" + price + ", shouldProduct=" + shouldProduct + "]"; } } //写两个线程 //消费者线程 class Customer implements Runnable { //由于两个线程需要共享一个资源,商品资源需要实例化,给Customer private Goods goods; public Customer(Goods goods) { this.goods = goods; } @Override public void run() { // TODO Auto-generated method stub //消费多个 无限制消费 while (true) { synchronized (goods) { //false goods 这个对象下面的一个属性叫shouldProduct if (!goods.isShouldProduct()) { //执行的不需要生产的代码 //开始直接购买 System.out.println("消费者购买了:" + goods.getName() + ",价格为:" + goods.getPrice()); //购买完以后,这个商品就没有了,需要生产,重新标记为true goods.setShouldProduct(true); //购买完以后商品没了,要去唤醒生产者 去干活,开始生产了 //唤醒生产者 goods.notify(); } else { //需要生产的代码,消费者进入到等待状态 System.out.println("3"); try { goods.wait();//没有商品的时候,需要生产的时候,消费者进入到阻状态 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("4"); } } } } } //生产者线程 class Productor implements Runnable { private Goods goods; public Productor(Goods goods) { this.goods = goods; } @Override public void run() { // TODO Auto-generated method stub int count = 0; while (true) { try { //让生产者线程睡一会 Thread.sleep(4000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } synchronized (goods) { if (goods.isShouldProduct()) { //需要生产 shouldProduct 变量true if (count % 2 == 0) { goods.setName("奥迪RS8"); goods.setPrice(54.3); } else { goods.setName("五菱神车"); goods.setPrice(20.9); } //生产完以后,立马标记为 false goods.setShouldProduct(false); System.out.println("生产者生产了:" + goods.getName() + ",价格为:" + goods.getPrice()); count++; //已经生产好了,去唤醒消费者,让消费者去消费 goods.notify(); } else { //不需生产 的话,就能直接 让生产者等待 System.out.println("1"); try { goods.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("2"); } } } } } public class Demo1 { public static void main(String[] args) { //false 不需要生产,证明有产品 Goods goods = new Goods("保时捷" , 67.8, false);//true 需要被生产 Customer customer = new Customer(goods); Productor productor = new Productor(goods); //想让哪个线程抢到合适? //消费者先抢到线程 new Thread(customer).start(); new Thread(productor).start(); } }