案例一:使用多线程完成三个窗口卖票(不能出现重复卖票以及负数票)
卖票程序SellTicket 这里使用Lock类中的方法实现加锁和释放锁!
package cn.itcast.thread2;
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();
private Object obj=new Object();
@Override
public void run() {
while (true) {
lock.lock();//这里也可以使用synchronized(obj){if中的代码} 要使用同一把锁
if (tickets > 0) {
try {
Thread.sleep(100);// 休息一会
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在卖第" + tickets-- + "张票");
}
lock.unlock();//释放锁
}
}
}
测试类
package cn.itcast.thread2;
public class SellTicketTest {
public static void main(String[] args) {
SellTicket s1=new SellTicket();
Thread t1=new Thread(s1);
Thread t2=new Thread(s1);
Thread t3=new Thread(s1);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
案例二:线程之间的通信
线程之间的通信就是对同一个数据的操作:举例说明-->
如卖包子,如果包子铺没有包子就让生产商产包子,同时顾客等待.如果包子铺有包子就卖包子,生产商就不能产包子,就等待包子铺卖完后才能生产包子!因此生产商等待!
代码:
学生类Student
package cn.itcast.thread3;
public class Student {
int age;
boolean flag;//默认是没有数据的false 如果有数据就为true
String name;
}
设置线程:
package cn.itcast.thread3;
/**
* 线程之间的通信
* 如果有学生就不set了
* @author Administrator
*
*/
public class SetThread implements Runnable{
public Student s;
private int x=0;
public SetThread(Student s){
this.s=s;
}
@Override
public void run() {
while(true){
synchronized (s) {//把要操作的student对象当成锁对象
if(s.flag){//判断有没有数据 如果有数据了就等着释放锁
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没有数据 就创建数据
if(x%2==0){//是偶数就创建李卫康
s.name="李卫康";
s.age=23;
}else{//是奇数就创建韩玮
s.name="韩玮";
s.age=22;
}
x++;//x++
//如果已经设置了数据就更改标记
s.flag=true;//有数据了就等着 因此说更改标记为true
s.notify();//唤醒
}
}
}
}
获取线程:
package cn.itcast.thread3;
public class GetThread implements Runnable{
public Student s;
public GetThread(Student s){
this.s=s;
}
@Override
public void run() {
while(true){
synchronized (s) {
if(!s.flag){//如果flag是false说明没有数据就不获取数据了就等着
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//有数据就打印
System.out.println("学生的姓名和年龄分别是:"+s.name+":"+s.age);
//修改标记
s.flag=false;//没数据了就等着
//唤醒
s.notify();//
}
}
}
}
测试类:
package cn.itcast.thread3;
public class Test {
public static void main(String[] args) {
//创建资源
Student s=new Student();
//设置和获取的类
GetThread get=new GetThread(s);
SetThread set=new SetThread(s);
Thread t1=new Thread(get);
Thread t2=new Thread(set);
//启动线程
t1.start();
t2.start();
}
}
运行结果: