------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
lock锁:接口
使用其子类对象
为保证被同步的代码块不出现异常,通常需要将解锁的过程放在final中,所以被同步的代码块也要放在try中
线程死锁:
当多个锁出现相互等待都不执行时,就出现线程死锁
死锁一般出现在锁的嵌套中,相互等着对方执行完毕,也就是双方都要执行对方已经加锁的代码
代码演示:
<span style="font-size:12px;">public class DeadLock extends Thread { // 定义一个标记用来指定要执行的代码 boolean flag; // 创建两个不同的锁对象 static Object o1 = new Object(); // 静态修饰的原因是保证锁的同步性!重要! static Object o2 = new Object(); /** * @param flag */ public DeadLock(boolean flag) { super(); this.flag = flag; } @Override public void run() { super.run(); if (flag) { //创建线程对象时,将flag赋值为true时,执行的代码 synchronized (o1) { System.out.println("if语句中o1的执行代码"); synchronized (o2) { System.out.println("if语句中o2的执行代码"); } } }else { //创建线程对象时,将flag赋值为false时,执行的代码 synchronized (o2) { System.out.println("else语句中o2的执行代码"); synchronized (o1) { System.out.println("else语句中o1的 执行代码"); } } } } }</span>
结合如下死锁测试代码,死锁过程为,当线程一进入之后判断条件语句,执行判断结果为true的同步锁代码,打印if中的语句,同时线程二进入判断条件语句,执行判断结果为false的同步锁代码,执行if中的语句,当两个线程继续向下执行时,各自的线程都没有出锁,而接下来的代码就是要执行对方线程的解锁后的代码,所以两个线程就互相 等待对方 执行完解锁,所以就形成了相互等待的死锁状态
死锁测试:
<span style="font-size:12px;">public class Test { public static void main(String[] args) { // 创建多线程对象 DeadLock lock1 = new DeadLock(true); DeadLock lock2 = new DeadLock(false); // 开启线程 lock1.start(); lock2.start(); } }</span>解决方案:
不出现锁的嵌套
满足条件后自己解锁,比如当线程等待时间超过一定时间,就自动杀掉线程
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
生产者消费者:
生产者与消费者共享同一个资源
满足生产者生产条件时,生产者生产
当满足消费者消费条件时,消费者消费
产者与消费者可以通过不同的线程完成相应的动作
等待唤醒机制:
要执行的线程由于某种需求需要别的线程对共享数据先进行操作时,这个线程就需要等待
当其他的线程操作完之后,应该唤醒刚才那个等待的线程
等待唤醒机制涉及到的类:
Thread:多个线程才会出现呢等待唤醒机制
锁:等待唤醒机制需要同步代码,既然有同步代码就需要锁(synchronize)
锁是Object类型:是线程等待,但是是线程通过锁等待
代码实现:
1.创建共享数据类
<span style="font-size:12px;">public class Person { // 封装成员属性 private String name; private int age; private boolean flag; // 提供判断条件用于区分生产者和消费者的执行路线 public boolean isFlag() { return flag; } public void setFlag(boolean flag) { // 对外提供公共的 修改标志条件的入口,是保证生产和消费一一对应的前提 this.flag = flag; } public Person() { // 创建空参的 构造函数用于创建共享对象的数据 super(); // TODO Auto-generated constructor stub } /** * @param name * @param age */ public Person(String name, int age) { super(); this.name = name; this.age = age; } // 对外提供公共的访问入口 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }</span>
2.创建生产者线程类
<span style="font-size:12px;">public class Set implements Runnable { int i=0; private Person p; /** * @param p */ public Set(Person p) { // 为什么呢? 因为创建线程的时候保证了生产者和消费者使用的是同一个对象 super(); this.p = p; } // 重写run方法 public void run() { while (true) { synchronized (p) { // 保证所共享的数据是同步的 if (p.isFlag()) { try { p.wait(); // 先进行判断,如果满足条件则生产,否则等待消费者消费 } catch (InterruptedException e) { e.printStackTrace(); } } // 判断生产的元素 if (i%2==0) { p.setName("龙女"); p.setAge(16); System.out.println(Thread.currentThread().getName()+p); }else { p.setName("过儿"); p.setAge(18); System.out.println(Thread.currentThread().getName()+p); } i++; //制造不同的循环生产条件 p.setFlag(true); // 改变标志,让消费者消费 p.notify(); // 唤醒消费者 } } } }</span>3.创建消费者线程类
public class Get implements Runnable { private Person p; /** * @param p */ public Get(Person p) { // 利用出入的对象作为共享数据源 super(); this.p = p; } // 重写run方法 public void run() { while (true) { synchronized (p) { // 判断标志 if (!p.isFlag()) { try { p.wait(); // 判断,如果满足条件则消费,否则等待生产者生产 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+p); } p.setFlag(false); // 改变标志,让生产线程执行 p.notify(); // 唤醒生产线程 } } } }4.测试生产者和消费者一一对应的运行结果
public class Test { public static void main(String[] args) { // 创建共享对象数据 Person p = new Person(); Set set = new Set(p); Get get = new Get(p); // 创建线程对象 Thread setThread = new Thread(set,"生产者"); Thread getThread = new Thread(get,"消费者"); // 同时开启生产者和消费者线程 setThread.start(); getThread.start(); } }
据的同步性,当生产者和消费者执行各自的线程时首先要进行判断,如果不满足条件则等待对方对共享数据的操作,然后改变判断条件,唤醒等待,如此反复执行下去
线程组:
用来组织线程
线程池:
程序在开辟新的线程时,要消耗大量的系统资源,频繁的创建及销毁线程会大大降低程序的效率
在程序开始时,只要创建一个线程池,将指定数量的线程开启,如果使用,就使用线程池中的线程,如果不使用,线程也不销毁,而是出于空闲状态,等待被再次使用
线程池可以线程的某些行为,比如销毁动作