java 多线程之synchronized wait/notify解决买票问题

时间:2021-10-06 04:43:13

一.Java线程具有五中基本状态

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就     绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

java 多线程之synchronized  wait/notify解决买票问题

二. Java多线程的创建及启动

1.继承Thread类,重写该类的run()方法。

两个线程同时运行,随机产生4位随机字符

 import java.util.Random;

 public class 多线程 {

     public static Object lock = new Object();

     public static void randomString() {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4; i++) {
int number = random.nextInt(62);
sb.append(str.charAt(number));
}
System.out.print(sb);
} public static void main(String[] args) { new Thread(new myTh1()).start();
new Thread(new myTh2()).start(); } } class myTh1 extends Thread {
@Override
public void run() {
while (true) { try {
synchronized (多线程.lock) {
多线程.randomString();
System.out.print("------"+Thread.currentThread().getName());
System.out.println();
}
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} class myTh2 extends Thread {
@Override
public void run() {
while (true) {
try {
synchronized (多线程.lock) {
多线程.randomString();
System.out.print("------"+Thread.currentThread().getName());
System.out.println();
}
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象

主线程和两个实现Runnable接口的线程同时运行,线程对象只运行5次。

 public class 多线程Runnable {

     public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} new Thread(new myTh3()).start();
new Thread(new myTh4()).start(); }
}
class myTh3 extends Thread{
int i=0;
@Override
public void run() {
while (i<5) {
System.out.println(Thread.currentThread().getName());
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
} } } class myTh4 implements Runnable{ int i=0;
@Override
public void run() {
while (i<5) {
System.out.println(Thread.currentThread().getName());
i++;
} }
}

3.synchronized, wait, notify结合:

解决问题三个人去买票,张某有20元,李某10元。赵某5元。电影票5元一张,售货员只有3张5元的

 /*问题:
* 三个人去买票,张某有20元,李某10元。赵某5元。
* 电影票5元一张,售货员只有3张5元的。
*
* 思路:
* 张某买了票就会少3张5元的
* 李某买了票就会少1张5元的
* 赵某买了票就会多1张5元的
* 所以有三种情况:
* 一。赵某先买,张李都可以买
* 二。张某先买,此时李某买不了,只能等待赵某买了,再买
* 三。李某先买,此时张某买不了,只能等待赵某买了,再买
*
* 静态常量:售货员总钱数 sum=3
*
* 1.创建三个线程分别为张某,李某,赵某
* 2.判断此时sum值,合适就买票,减去相应的钱数,不合适就等待。
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class 多线程3 { public static int sum = 3;//设置零钱总张数为3张
public static Object look = new Object();//建立一个锁 public static List<Thread> arrayList = new ArrayList<>();//建立集合 保存这三个购买人的线程 public static void main(String[] args) throws InterruptedException {
//随机将赵某李某张某添加到集合中
arrayList.add(new li());
arrayList.add(new zhang());
arrayList.add(new zhao()); //通过迭代器遍历集合
Iterator<Thread> iterator = arrayList.iterator(); while (iterator.hasNext()) {
//获取线程
Thread t = iterator.next();
//线程启动
t.start();
//线程睡眠
t.sleep(2000);
} }
}
/**
* 张某线程
* @author Administrator
*
*/
class zhang extends Thread {
@Override
public void run() {
//因为要判断等待和唤醒,并且操作sum,所以在此处加锁
synchronized (多线程3.look) {
while (多线程3.sum < 3) {
try {
System.out.println("因为此时零钱不足:"+多线程3.sum+"张");
System.out.println("所以张某没买到电影票,等待购买");
多线程3.look.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} if (多线程3.sum > 2) {
多线程3.sum = 多线程3.sum - 3;
多线程3.look.notify();
System.out.println("张某买到了电影票");
System.out.println("此时零钱数为:"+多线程3.sum+"张");
}
}
}
}
/**
* 李某线程
* @author Administrator
*
*/
class li extends Thread {
@Override
public void run() {
synchronized (多线程3.look) {
while (多线程3.sum < 1) {
try {
System.out.println("因为此时零钱不足:"+多线程3.sum+"张");
System.out.println("所以李某没买到电影票,等待购买");
多线程3.look.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} if (多线程3.sum >= 1) {
多线程3.sum = 多线程3.sum - 1;
多线程3.look.notify();
System.out.println("李某买到了电影票");
System.out.println("此时零钱数为:"+多线程3.sum+"张");
} }
}
}
/**
* 赵某线程
* @author Administrator
*
*/
class zhao extends Thread {
@Override
public void run() {
synchronized (多线程3.look) {
if (多线程3.sum >= 0) {
多线程3.sum = 多线程3.sum + 1;
System.out.println("赵某买到了电影票");
System.out.println("此时零钱数为:"+多线程3.sum+"张");
多线程3.look.notify();
}
}
}
}

全部都是培训课后习题,最后一个足足搞了半天,希望我写的没毛病,求指教。。谢谢大佬。