java 多线程之synchronized wait/notify解决买票问题
一.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多线程的创建及启动
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();
}
}
}
}
全部都是培训课后习题,最后一个足足搞了半天,希望我写的没毛病,求指教。。谢谢大佬。
java 多线程之synchronized wait/notify解决买票问题的更多相关文章
- java多线程之wait和notify协作,生产者和消费者
这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...
- Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition
前言:这几天看了很多关于多线程的知识,分享一波.(但是目前接触的项目还未用到过,最多用过线程池,想看线程池 请看我之前的博客) 关于基本的理论等 参考如下: https://www.cnblogs.c ...
- JAVA多线程之Synchronized、wait、notify实例讲解
一.Synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争 ...
- (二)java多线程之synchronized
本人邮箱: kco1989@qq.com 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco github: https://github.com/kco198 ...
- JAVA多线程之Synchronized关键字--对象锁的特点
一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...
- Java多线程之synchronized及其优化
Synchronized和同步阻塞synchronized是jvm提供的同步和锁机制,与之对应的是jdk层面的J.U.C提供的基于AbstractQueuedSynchronizer的并发组件.syn ...
- java多线程之wait和notify
多线程中的通信是非常重要的概念,线程直接实现通信就可以并发完成很多复杂工作. java在Object类中就设计了wait()和notify()两个方法,以解决这个问题. 1.释义: wait()方法将 ...
- Java多线程之Wait()和Notify()
1.Wait()和Notify.NotifyAll都是Object的方法 2.多线程的协作是通过控制同一个对象的Wait()和Notify()完成 3.当调用Wait()方法时,当前线程进入阻塞状态, ...
- Java多线程之synchronized(三)
在多线程访问同一个对象中的不同的synchronized方法或synchronized代码块的前提下,也就是“对象监控器”为同一个对象的时候,也就是synchronized的锁为同一把锁的时候,调用的 ...
随机推荐
- CentOS7安装步骤
CentOS7安装详解 本文基于vmware workstations进行CentOS7安装过程展示,关于vmware workstations安装配置本人这里不再介绍,基本过程相当于window ...
- windows上安装Anaconda和python的教程详解
一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因 ...
- html Servlet web.xml(转)
在浏览器输入:http://127.0.0.1:8080/test/test.html点击提交按钮,Tomcat后台输出:control: aaa's value is : bbb页面显示结果:pag ...
- spring boot + mybatis 访问 neo4j
之前有通过rest的风格去访问,但是每次需要访问时候将statement一并加入header中去数据库执行,方式简单.且思路清晰,但是不便于形成模板调用,固采用mybaits来集成. 1.关键pom. ...
- Timer和DispatcherTimer简单使用
1. 设定计时器相关属性,使用委托方法处理事件触发 DispatcherTimer dispatcherTimer= new DispatcherTimer(); dispatcherTimer.Ti ...
- mysql通过日志恢复数据库
案例:http://www.linuxidc.com/Linux/2012-11/74005.htm http://blog.csdn.net/ssrc0604hx/article/details/1 ...
- 【JZOJ2224】【NOI2006】最大获利
题目描述 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成 ...
- 深入理解spring注解之@ComponentScan注解
今天主要从以下几个方面来介绍一下@ComponentScan注解: @ComponentScan注解是什么 @ComponentScan注解的详细使用 1,@ComponentScan注解是什么 其实 ...
- KiCad 5.1.3 尝鲜版已经有了
KiCad 5.1.3 尝鲜版已经有了 发现一个改动. 对调了对话框按钮的位置,和 Windows 习惯一样了.
- HZOJ trade
强烈谴责$skyh$的没$\Huge 脸$行为. 很经典的可反悔贪心,然而我一直以为是sbdp还一直想着怎么优化…… 正常的贪心肯定是不对的. 但是由于A-C=A-B+B-C, 所以用一个小根堆维护, ...