1.创建线程的方法(这里不考虑继承Thread类)
通过实现Runnable接口的方式实现
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"执行了....");
}
}
}
public class Test01 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);// 也可以直接写匿名类
thread.start();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"执行了....");
}
}
}
2.同步代码块
同一个时间,只有一个线程可以运行,锁住
注意,必须是同一把锁,当然,由于基本数据类型的特殊性,有些基本数据类型也是可以锁住的,比如 Integer = (0-127) 之内是可以充当锁的,当然,锁只能锁住使用他的线程。
1.格式
synchronized(任意对象){
可能出现线程安全的代码
}
2.代码
public class Test {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread t1 = new Thread(ticket, "赵四");
Thread t2 = new Thread(ticket, "广坤");
Thread t3 = new Thread(ticket, "刘能");
//开启线程
t1.start();
t2.start();
t3.start();
}
}
public class Ticket implements Runnable{
int ticket = 100;
//创建一个对象充当锁对象
Object obj = new Object();
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
if (ticket>0){
System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
ticket--;
}
}
}
}
}
3.同步方法
1.介绍
关键字是synchrosnized 锁 this
所以,runnable的实现类要是同一个对象
或者使用static方法 这时候锁就是 类.class
2.代码块
public class Ticket implements Runnable {
int ticket = 100;
@Override
public void run() {
while (true) {
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
method();
}
}
/* public synchronized void method() {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");
ticket--;
}
}*/
public void method() {
synchronized (this){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");
ticket--;
}
}
}
}
4.关于对一个类的不同业务的思考
如果对一个类的不同业务处理,应该怎么处理呢?
线程如果对一个类进行操作,或者根据一个类的数据进行相应的方法调用?
首先第一点,必须要拿到这个类的数据,所以,必须要拿到这个类的对象,或者是这个类的子类。
- 将业务方法写在类中,然后通过类的对象进行调用
- 将业务方法写在线程类中,线程类中存一个类的对象。
1.包子铺代码
做一个卖一个
//包子铺代码 操作对象
public class BaoZiPu {
//定义一个count证明生产包子,消费包子
private int count;
//定义一个flag,证明有没有包子
private boolean flag;
public BaoZiPu() {
}
public BaoZiPu(int count, boolean flag) {
this.count = count;
this.flag = flag;
}
//专门给消费线程服务
public void getCount() {
System.out.println("消费了第"+count+"个包子...........");
}
//专门给生产线程服务
public void setCount() {
count++;
System.out.println("生产了第"+count+"个包子....");
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
// 实现类
public class Consumer implements Runnable{
private BaoZiPu baoZiPu;
public Consumer(BaoZiPu baoZiPu){
this.baoZiPu = baoZiPu;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (baoZiPu){
//如果flag等于false.证明没有包子,消费线程等待
if (baoZiPu.isFlag() == false){
try {
baoZiPu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果flag为true,证明有包子,消费包子,然后唤醒生活线程
baoZiPu.getCount();
//改变flag状态为false,证明没有包子了
baoZiPu.setFlag(false);
//唤醒生产线程
baoZiPu.notify();
}
}
}
}
public class Product implements Runnable{
private BaoZiPu baoZiPu;
public Product(BaoZiPu baoZiPu){
this.baoZiPu = baoZiPu;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (baoZiPu){
//如果flag等于true.证明有包子,生产线程等待
if (baoZiPu.isFlag() == true){
try {
baoZiPu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程
baoZiPu.setCount();
//改变flag状态为true,证明有包子了
baoZiPu.setFlag(true);
//唤醒消费线程
baoZiPu.notify();
}
}
}
}
public static void main(String[] args) throws Exception{
BaoZiPu baoZiPu = new BaoZiPu();
Thread t1 = new Thread(new Product(baoZiPu));
Thread t2 = new Thread(new Consumer(baoZiPu));
t1.start();
t2.start();
}
问题:
1.为什么wait不能放在最后执行
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (baoZiPu){
//如果flag等于true.证明有包子,生产线程等待
if (baoZiPu.isFlag() == true){
//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程
baoZiPu.setCount();
//改变flag状态为true,证明有包子了
baoZiPu.setFlag(true);
//唤醒消费线程
baoZiPu.notify();
try {
baoZiPu.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
因为notify是将线程唤醒,线程是跟着wait继续走的,这时候直接循环,但是,如果拿到锁却拿不到条件,直接卡死在这里了
2.多生产多消费的包子铺
notifyAll 但是这样还是消耗资源比较严重,因为有可能出现多次重复拿到锁但是无法运行放弃锁,并且有些拿不到锁的也唤醒了.
public class BaoZiPu {
//定义一个count证明生产包子,消费包子
private int count;
//定义一个flag,证明有没有包子
private boolean flag;
public BaoZiPu() {
}
public BaoZiPu(int count, boolean flag) {
this.count = count;
this.flag = flag;
}
//专门给消费线程服务
public synchronized void getCount() {
//如果flag等于false.证明没有包子,消费线程等待
while (flag == false) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果flag为true,证明有包子,消费包子,然后唤醒生活线程
System.out.println("消费了第" + count + "个包子...........");
//改变flag状态为false,证明没有包子了
flag = false;
//唤醒生产线程
this.notifyAll();
}
//专门给生产线程服务
public synchronized void setCount() {
//如果flag等于true.证明有包子,生产线程等待
while (flag == true) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程
count++;
System.out.println("生产了第" + count + "个包子....");
//改变flag状态为true,证明有包子了
flag = true;
//唤醒消费线程
this.notifyAll();
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
public class Consumer implements Runnable{
private BaoZiPu baoZiPu;
public Consumer(BaoZiPu baoZiPu){
this.baoZiPu = baoZiPu;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
baoZiPu.getCount();
}
}
}
public class Product implements Runnable{
private BaoZiPu baoZiPu;
public Product(BaoZiPu baoZiPu){
this.baoZiPu = baoZiPu;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
baoZiPu.setCount();
}
}
}
public class Test01 {
public static void main(String[] args) {
//创建包子铺对象
BaoZiPu baoZiPu = new BaoZiPu();
Product product = new Product(baoZiPu);
Consumer consumer = new Consumer(baoZiPu);
//两个生产线程
new Thread(product).start();
new Thread(product).start();
//两个消费线程
new Thread(consumer).start();
new Thread(consumer).start();
}
}
5.Lock
1. 介绍
Lock lock = new ReentrantLock();
lock.lock();// 加锁
lock.unlock(); // 解锁
6.condition阻塞队列
void await() ->线程等待 // 让当前线程等等
void signal()->线程唤醒 // 从队列中唤醒一个等待线程
Condition condition = lock.newCondition();
可以分业务唤醒队列,一个队列一个业务
1.包子例题
public class BaoZiPu {
//定义一个count证明生产包子,消费包子
private int count;
//定义一个flag,证明有没有包子
private boolean flag;
//创建Lock对象
Lock lock = new ReentrantLock();
//为生产者创建Condition对象
Condition productCondition = lock.newCondition();
//为消费者创建Condition对象
Condition consumerCondition = lock.newCondition();
public BaoZiPu() {
}
public BaoZiPu(int count, boolean flag) {
this.count = count;
this.flag = flag;
}
//专门给消费线程服务
public void getCount() {
//获取锁
lock.lock();
//如果flag等于false.证明没有包子,消费线程等待
while (flag == false) {
try {
//消费线程等待
consumerCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果flag为true,证明有包子,消费包子,然后唤醒生活线程
System.out.println("消费了第" + count + "个包子...........");
//改变flag状态为false,证明没有包子了
flag = false;
//唤醒生产线程
productCondition.signal();
//释放锁
lock.unlock();
}
//专门给生产线程服务
public void setCount() {
//获取锁
lock.lock();
//如果flag等于true.证明有包子,生产线程等待
while (flag == true) {
try {
//生产线程等待
productCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程
count++;
System.out.println("生产了第" + count + "个包子....");
//改变flag状态为true,证明有包子了
flag = true;
//唤醒消费线程
consumerCondition.signal();
//释放锁
lock.unlock();
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
public class Consumer implements Runnable{
private BaoZiPu baoZiPu;
public Consumer(BaoZiPu baoZiPu){
this.baoZiPu = baoZiPu;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
baoZiPu.getCount();
}
}
}
public class Product implements Runnable{
private BaoZiPu baoZiPu;
public Product(BaoZiPu baoZiPu){
this.baoZiPu = baoZiPu;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
baoZiPu.setCount();
}
}
}
public class Test01 {
public static void main(String[] args) {
//创建包子铺对象
BaoZiPu baoZiPu = new BaoZiPu();
Product product = new Product(baoZiPu);
Consumer consumer = new Consumer(baoZiPu);
//两个生产线程
new Thread(product).start();
new Thread(product).start();
//两个消费线程
new Thread(consumer).start();
new Thread(consumer).start();
}
}