Java多线程-Lock锁的使用,以及生产者和消费者的实现
Posted Frank Q
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程-Lock锁的使用,以及生产者和消费者的实现相关的知识,希望对你有一定的参考价值。
本文中将主要介绍Java多线程编程基础中的Lock锁对象的使用,以及如何一步一步实现Java代码的生产者与消费者;
1、Java中如何使用Lock锁以及死锁问题的描述
2、Java实现生产者与消费者的过程(一步一步优化的步骤)
1、Java中如何使用Lock锁以及死锁问题的描述
LOCK锁的出现:为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象LOCK;
Lock锁中最重要的个方法:
void lock()
void unlock()
下面就是Lock锁的一个简单的演示Demo,之后的死锁问题也会使用Lock锁来进行表现;
1)例子一:利用Lock对象实现售票机制:
SellTicket.java
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SellTicket implements Runnable
// 定义票
private int tickets = 100;
// 定义锁对象
private Lock lock = new ReentrantLock();
@Override
public void run()
while (tickets > 0)
// 之所以不带catch是因为保证在出错的情况下保证锁的释放
try
// 加锁
lock.lock();
if (tickets > 0)
try
Thread.sleep(100);
catch (InterruptedException e)
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets-- + "张票" );
finally
// 释放锁
lock.unlock();
SellTicketDemo.java
public class SellTicketDemo
public static void main(String[] args)
// 创建资源对象
SellTicket st = new SellTicket();
// 创建窗口
Thread thread1 = new Thread(st, "窗口一");
Thread thread2 = new Thread(st, "窗口二");
Thread thread3 = new Thread(st, "窗口三");
// 开启线程
thread1.start();
thread2.start();
thread3.start();
运行效果:
可以看见线程在运行的时候,基本上都是成片运行的,并没有比较好的交叉运行
2)例子二:利用Lock实现死锁机制
MyLock.java
/**
* 创建两把锁可以直接调用
* @author YQ
*
*/
public class MyLock
//创建两把锁对象
public static final Object objA = new Object();
public static final Object objB = new Object();
DieLock.java
public class DieLock extends Thread
private boolean flag;
public DieLock(boolean flag)
this.flag = flag;
@Override
public void run()
if (flag)
synchronized (MyLock.objA)
System.out.println("if ObjA");
synchronized (MyLock.objB)
System.out.println("if ObjB");
else
synchronized (MyLock.objB)
System.out.println("else ObjB");
synchronized (MyLock.objA)
System.out.println("else ObjA");
DieLockDemo.java
/**
* 同步的弊端:
* A:效率低
* B:容易产生死锁
* 死锁:
* 两个或者两个以上的线程在争夺资源的过程中,发生的一种互相等待的现象
* @author YQ
*/
public class DieLockDemo
public static void main(String[] args)
DieLock dieLock1 = new DieLock(true);
DieLock dieLock2 = new DieLock(false);
dieLock1.start();
dieLock2.start();
运行效果:
2、Java实现生产者与消费者的过程(一步一步优化的步骤)
1)初始实现,定义一个Student的JavaBean的类,然后通过set保存Student的数据作为生产者,之后通过get取出Student的数据作为消费者,但是以下的实现仅仅只有一次!
Student.java
public class Student
private String name;
private int 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 "Student [name=" + name + ", age=" + age + "]";
SetThread.java
public class SetThread extends Thread
private Student student;
public SetThread(Student student)
super();
this.student = student;
@Override
public void run()
student.setName("admin");
student.setAge(24);
GetThread.java
public class GetThread extends Thread
private Student student;
public GetThread(Student student)
super();
this.student = student;
@Override
public void run()
System.out.println(student.getName() + "====" + student.getAge());
StudentDemo.java
public class StudentDemo
public static void main(String[] args)
// 创建两个线程的共用资源
Student student = new Student();
// 创建生产者和消费者
SetThread thread1 = new SetThread(student);
GetThread thread2 = new GetThread(student);
//开启生产者和消费者线程
thread1.start();
thread2.start();
运行效果:
2)进一步的循环实现多次生产多次消费,使用的是同步的方式
Student.java代码同上!
GetThread.java
public class GetThread extends Thread
private Student student;
public GetThread(Student student)
super();
this.student = student;
@Override
public void run()
while (true)
synchronized (student)
System.out.println(student.getName() + "====" + student.getAge());
SetThread.java
public class SetThread extends Thread
private Student student;
private int x = 0;
public SetThread(Student student)
super();
this.student = student;
@Override
public void run()
while (true)
//必须是相同的同一把锁
synchronized (student)
if (x%2 == 0)
student.setName("admin");
student.setAge(24);
else
student.setName("manager");
student.setAge(28);
x++;
StudentDemo.java
public class StudentDemo
public static void main(String[] args)
// 创建两个线程的共用资源
Student student = new Student();
// 创建生产者和消费者
SetThread thread1 = new SetThread(student);
GetThread thread2 = new GetThread(student);
//开启生产者和消费者线程
thread1.start();
thread2.start();
运行效果(停止的时候出现的ad没有完整与线程的实现没有关系,主要是因为命令窗口的缓冲没有完整的原因):
3)真正实现生产者与消费者:生产者生产后消费者才可以消费,消费者消费之后生产者才可以生产如此往复:
Student.java
public class Student
private String name;
private int age;
//默认情况下不存在数据
private boolean flag;
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;
public boolean isFlag()
return flag;
public void setFlag(boolean flag)
this.flag = flag;
@Override
public String toString()
return "Student [name=" + name + ", age=" + age + "]";
SetThread.java
public class SetThread extends Thread
private Student student;
private int x = 0;
public SetThread(Student student)
super();
this.student = student;
@Override
public void run()
while (true)
// 必须是相同的同一把锁
synchronized (student)
// 判断
if (student.isFlag())
try
student.wait();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
if (x%2 == 0)
student.setName("admin");
student.setAge(24);
else
student.setName("manager");
student.setAge(28);
x++;
// 修改标记
student.setFlag(true);
student.notify();
GetThread.java
public class GetThread extends Thread
private Student student;
public GetThread(Student student)
super();
this.student = student;
@Override
public void run()
while (true)
synchronized (student)
if (!student.isFlag())
try
student.wait();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(student.getName() + "====" + student.getAge());
student.setFlag(false);
student.notify();
运行效果:
StudentDemo.java
/**
* 等待唤醒:
* Object类中提供了三个方法:
* wait():等待;
* notify():唤醒单个线程;
* notifyAll():唤醒所有线程;
* @author YQ
*
*/
public class StudentDemo
public static void main(String[] args)
// 创建两个线程的共用资源
Student student = new Student();
// 创建生产者和消费者
SetThread thread1 = new SetThread(student);
GetThread thread2 = new GetThread(student);
//开启生产者和消费者线程
thread1.start();
thread2.start();
运行效果:
以上是关于Java多线程-Lock锁的使用,以及生产者和消费者的实现的主要内容,如果未能解决你的问题,请参考以下文章