一. 线程之间的通信
1.1wait()等待将当前线程从运行状态便到阻塞状态(释放对象锁)
1.2 noytify()
只唤醒一个对应对象所的一个线程
1.3 notifyAll()
唤醒全部对应对象所的线程
public class Demo01 {
public static void main(String[] args) {
/*线程之间的通信:多线程之间的
* wait()等待 将当前线程从运行状态便到阻塞状态(释放对象锁)
* noytify() 只唤醒一个对应对象所的一个线程
* notifyAll() 唤醒全部对应对象所的线程
*
* 上面三个方法:是属于Object类的,不是线程特有的方法
*
*上诉方法要在同步代码里面使用才有意义
*/
MyThread13 th=new MyThread13();
try {
th.notify();
} catch (Exception e) {
// TODO: handle exception
}
}
}
class MyThread13 extends Thread{
}
二.线程安全问题
public class LockDemo02 {
public static void main(String[] args) {
/*线程安全问题:仅限于多线程
* 锁对象的概念:
* 在JAVA中每一个对象都有一个内置的对象锁,并且整个锁只有一把钥匙。
* 这就决定了当一个线程获取了该对象锁的时候别的线程无法再去获取,只有当获取对象锁的线程释放了锁以后才能去使用。
*
* 常用两种锁对象的方式:
* 一种是对象,
* 一种是class文件 (类.class 或者对象.getClass())
*
* 1.同步代码块 本质锁对象
* 2.同步方法 (普通的方法 以及静态方法)
* 同步普通方法锁的也是对象
* 同步静态方法锁的是 字节码文件 (.class)
*
*/
Mythread11 th=new Mythread11();
Thread th1=new Thread(th,"窗口1");
Thread th2=new Thread(th,"窗口2");
Thread th3=new Thread(th,"窗口3");
th1.start();
th2.start();
th3.start();
}
}
class Mythread11 implements Runnable{
private int ticket=50;
@Override
public void run() {
// while(true){
// synchronized (Mythread11.class) {//同步代码块
// if(ticket>0){
// try {
// Thread.sleep(200);
// } catch (Exception e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName()+"D360还剩"+ticket+"张票");
// ticket--;
// }
// else{
// System.out.println("很遗憾,没票了");
// break;
// }
// }
//
// }
method(); //调用同步方法
}
//同步方法 同步可以定义在 自定义的类当中,不限于线程类
public synchronized void method(){
while(true){
synchronized (Mythread11.class) {//同步代码块
if(ticket>0){
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"D360还剩"+ticket+"张票");
ticket--;
}
else{
System.out.println("很遗憾,没票了");
break;
}
}
}
}
}
2.1仅限于多线程
2.2 锁对象的概念在JAVA中每一个对象都有一个内置的对象锁,并且整个锁只有一把钥匙。
* 这就决定了当一个线程获取了该对象锁的时候别的线程无法再去获取,只有当获取对象锁的线程释放了锁以后才能去使用。
一种是对象
常用两种锁对象的方式:
一种是class文件 (类.class 或者对象.getClass())
2.3 线程退让
public class YieldDemo {
public static void main(String[] args) {
/*线程退让
* 线程的优先级:默认优先级为5
* 注意:线程在执行过程中不能改变优先级,必须在线程开启之前设置优先级
* 范围:1-10数字越大优先级越大
*/
MyThread10 th=new MyThread10();
th.setName("线程一");
th.setPriority(Thread.MAX_PRIORITY); //最大优先级
System.out.println(th.getPriority());
MyThread10 th1=new MyThread10();
th1.setName("线程二");
th1.setPriority(Thread.MIN_PRIORITY);
th.start();
th1.start();
}
}
class MyThread10 extends Thread{
int i=1;
@Override
public void run() {
while(i<100){
if(i==50){
Thread.yield(); //线程让步
}
System.out.println(Thread.currentThread().getName()+"=="+i);
i++;
}
}
}
线程的优先级
默认优先级为5注意:线程在执行过程中不能改变优先级,必须在线程开启之前设置优先级
范围:1-10数字越大优先级越大
三.生产者和消费者模式
3.1 Clerk
//商店类
public class Clerk {
/*
* 主要负责两个内容:
* 1.有货通知消费者去买东西
* 1.1
* 2.没货的时候通知生产者生产东西
* 2.1
*
*
* wait:在当前运行线程调用的时候回主动释放掉对象锁并进入到阻塞的状态,如果该线程想恢复到就绪状态,则必须等到同一个对象
* 调用notify/notifyAll()方法才行
*
* 概念:线程池
*/
private int goodsNum=20; //默认商店目前有最大持有商品数
//生产者的
public synchronized void add(){
if(goodsNum>=20){//货满的时候
System.out.println("sorry,商店期货过多,请稍停生产");
try {
this.wait();//让生产者等地
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
++goodsNum;
System.out.println("生产了第"+goodsNum+"个商品给"+Thread.currentThread().getName());
this.notify();//唤醒通知生产者可以生产商品
}
}
//消费者
public synchronized void sell(){
if(goodsNum<=0){
System.out.println("sorry,商店没货 了");
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println("卖了第"+goodsNum+"个商品给"+Thread.currentThread().getName());
goodsNum--;
this.notify();
}
}
3.2 Consumer
public class Consumer implements Runnable {
private Clerk clerk;
public Consumer(Clerk clerk) {
super();
this.clerk = clerk;
}
@Override
public void run() {
while(true){
try {
Thread.sleep((int)(Math.random()*1000));
} catch (Exception e) {
// TODO: handle exception
}
clerk.sell();
}
}
}
3.3 Productor
//生产者一个线程类
public class Productor implements Runnable{
private Clerk clerk;
public Productor(Clerk clerk) {
super();
this.clerk = clerk;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.add();//
}
}
}
3.4 TestDemo
public class TestDemo {
public static void main(String[] args) {
/*
*
*测试类
*
*/
Clerk clerk=new Clerk();
Productor pro =new Productor(clerk);
Consumer con=new Consumer(clerk);
Thread th1=new Thread(pro,"生产者一");
Thread th2=new Thread(con,"消费者一");
th1.start();
th2.start();
}
}
四. 死锁和同步静态方法锁
4.1 死锁当一个线程拥有另一个线程的资源所得时候,而另一个也拥有该线程的资源所。
* 彼此都必须在获得对方资源锁的时候才能持续运行。
* 当两方都不退让的时候,就会陷入一种僵持状态----死锁
public class DeadLockDemo {
public static void main(String[] args) {
/*死锁:当一个线程拥有另一个线程的资源所得时候,而另一个也拥有该线程的资源所。
* 彼此都必须在获得对方资源锁的时候才能持续运行。
* 当两方都不退让的时候,就会陷入一种僵持状态----死锁
*
* 产生的前提是:
* 线程之间持有相同的对象锁,获取对象锁的顺序反过来。。
*/
Battery battery =new Battery("南孚");
Controler controler=new Controler("遥控器");
//
new Thread(new Runnable() {
@Override
public void run() {
synchronized (controler) { //有遥控器没电池
System.out.println("小妹啊,我手里拿着遥控器,你不给电池我我就不给遥控器你");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//在等待电池
synchronized (battery) {
System.out.println("哈哈哈哈,终于可以看喜洋洋了");
}
}
}
},"小明").start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (battery) {
System.out.println("哥哥,我手里拿着电池,你不给遥控器我就不给电池你,哼。。。");
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
synchronized (controler) {
System.out.println("还是哥哥好,终于给遥控器我了,哈哈哈哈。。");
}
}
}
} ,"小红").start();
}
}
//电池类
class Battery{
public String name;
public Battery(String name) {
super();
this.name = name;
}
}
//遥控器类
class Controler{
public String name;
public Controler(String name) {
super();
this.name = name;
}
}
4.1.1 产生的前提是:
* 线程之间持有相同的对象锁,获取对象锁的顺序反过来。
同步静态方法锁的是什么?
* 锁的是字节码文件,不是对象
public class StaticDemo {
public static void main(String[] args) {
/*同步静态方法锁的是什么?
* 锁的是字节码文件,不是对象
*
*
*
*/
Test test1=new Test();
Test test2=new Test();
MyThread12 th1=new MyThread12(test1);
MyThread12 th2=new MyThread12(test2);
th1.setName("线程一");
th2.setName("线程二");
th1.start();
th2.start();
}
}
class Test{
//同步静态方法
public synchronized static void fun(){
System.out.println(Thread.currentThread().getName()+"进入fun()方法");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"离开fun()方法");
}
public void fun2(){
fun(); //调用同步静态方法
}
}
class MyThread12 extends Thread{
private Test test;
public MyThread12(Test test) {
super();
this.test = test;
}
@Override
public void run() {
test.fun2(); //
}
}