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的锁为同一把锁的时候,调用的 ...
随机推荐
- 【JZOJ5093】【GDSOI2017第四轮模拟day3】字符串匹配 哈希
题面 对于一个字符集大小为C的字符串P,我们可以将任意两种字符在P中的位置进行互换,例如P=abcba,我们交换a,b就变为bacab,交换a,d就变为dbcbd,交换可以进行任意次.若交换后P变为了 ...
- Leetcode697.Degree of an Array数组的度
给定一个非空且只包含非负数的整数数组 nums, 数组的度的定义是指数组里任一元素出现频数的最大值. 你的任务是找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度. 示例 1: 输入: [ ...
- LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III
136. Single Number Given an array of integers, every element appears twice except for one. Find that ...
- LintCode刷题笔记-- Update Bits
标签: 位运算 描述: Given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set ...
- R语言实现Xbar-R控制图
R语言实现Xbar-R控制图 Xbar-R控制图在质量管理中主要用于对计量数据进行检测,以达到控制对象质量的目的. 虽然用Excel可以轻松实现控制图的操作,不过作为R软件初学者,我试着用仅有的一点R ...
- 三、python-json、正则
一.json 1.导入模块 import json 2.常用方法 dumps:序列化,把一个Python对象转化成json字符串 loads:反序列化,把json字符串转化成python dump ...
- Linux 下的mysql+centos7+主从复制
mysql+centos7+主从复制 MYSQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公 ...
- springMVC controller间跳转 重定向 传递参数的方法
springMVC controller间跳转 重定向 传递参数的方法 spring MVC框架controller间跳转,需重定向.有几种情况:不带参数跳转,带参数拼接url形式跳转,带参数不拼接参 ...
- BZOJ 4551树题解
好吧,洛谷的数据比较水暴力就可以过....(而且跑到飞快) 不过(BZ水不过去)还是讲讲正规的做法. 其实一眼可以看出可以树剖,但是,码起来有点麻烦. 其实有一种更简单的离线做法. 我们很容易联想到并 ...
- datetimepicker —— 日期选择控件
一.依赖 <link rel="stylesheet" href="css/bootstrap.min.css"> <link rel=&qu ...