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的锁为同一把锁的时候,调用的 ...
随机推荐
- update批量更新某一列成其它列对应的值【原】
update批量更新某一列成其它列对应的值 postgresql 标准sql语句 update AA set name = BB.name , AA.sex = BB.sex from BB wher ...
- php后端对跳转的封装
php后端对跳转的封装 /** * 页面跳转 * $url 跳转地址 * $time 一段时间后跳转 */ function app_redirect($url,$time=0,$msg='') { ...
- SDUT-3404_数据结构实验之排序七:选课名单
数据结构实验之排序七:选课名单 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 随着学校规模的扩大,学生人数急剧增加,选 ...
- 【风马一族_php】数组函数
原文来自:http://www.cnblogs.com/sows/p/6045699.html (博客园的)风马一族 侵犯版本,后果自负 2016-11-09 15:56:26 数组 函数 php- ...
- Zabbix清理历史数据库,缩减表大小
zabbix 由于历史数据过大, 因此导致磁盘空间暴涨, 下面是解决方法步骤: 一.分析数据库: 1. 统计数据库中每个表所占的空间: mysql> SELECT table_name AS ...
- Project configuration is not up-to-date with pom.xml. Run Maven->Update Project or use Quick Fix
版权声明:本文为 testcs_dn(微wx笑) 原创文章,非商用自由转载-保持署名-注明出处.谢谢. https://blog.csdn.net/testcs_dn/article/details/ ...
- 使用UITextView的dataDetectorTypes实现超链接需要注意的事项!
项目中需要在UITextView上识别URL,手机号码.邮箱地址等等信息.那么就用到了它的dataDetectorTypes属性.我的UITextView加在UITableViewCell上面的,当单 ...
- HZOJ 导弹袭击
比较显然的一个性质是如果存在$a(i)>=a(j) \& \& b(i)>=b(j)$那么j没用. 我们并不需要A,B的具体取值,我们之关心$\frac {A}{B}$. ...
- Mysql----linux下安装和使用
一.安装 安装环境centOS,MySQL 使用yum安装mysql 1. 下载rpm [root@CoderMrD admin]# wget -i -c http://dev.mysql.com/g ...
- Myeclipse 方法中文注释看不到
参考以下几种解决方式: 1 改变整个文件类型的编码格式 1) eclipse->window->preferences->General->Content Types 2) 找 ...