Java多线程_复习(更新中!!)
java多线程的常见例子
一.相关知识:
Java多线程程序设计到的知识:
(一)对同一个数量进行操作
(二)对同一个对象进行操作
(三)回调方法使用
(四)线程同步,死锁问题
(五)线程通信
等等
二.示例一:三个售票窗口同时出售20张票;
程序分析:1.票数要使用同一个静态值
2.为保证不会出现卖出同一个票数,要java多线程同步锁。
设计思路:1.创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖完!
2.创建主方法调用类
(一)创建一个站台类,继承Thread
package com.com.shundong.thread; /** * @ClassName Station * @Description 三个售票窗口同时出售20张票 * @Author shundong * @Date 2018/12/8 12:31 AM * @Version 1.0 **/ public class Station extends Thread { // 通过构造方法给线程名字赋值 public Station(String name) { super(name);// 给线程名字赋值 } // 为了保持票数的一致,票数要静态 static int tick = 20; // 创建一个静态钥匙 static Object ob = "test";//值是任意的 // 重写run方法,实现买票操作 @Override public void run() { while (tick > 0) { synchronized (ob) {// 这个很重要,必须使用一个锁, // 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来 if (tick > 0) { System.out.println(getName() + "卖出了第" + tick-- + "张票"); //tick--; } else { System.out.println("票卖完了"); } } try { sleep(1000);//休息一秒 } catch (InterruptedException e) { e.printStackTrace(); } } } // for test public static void main(String[] args) { Station station1 = new Station("站台一"); Station station2 = new Station("站台二"); Station station3 = new Station("站台仨"); station1.start(); station2.start(); station3.start(); } }
程序运行结果:
可以看到票数是不会有错的!
三.示例二:两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!
程序分析:钱的数量要设置成一个静态的变量。两个人要取的同一个对象值。 取钱的方法一定要同步
(一)创建一个Bank类
package com.shundong.day1; /** * @ClassName Bank * @Description 银行 内置柜台 和 ATM 两张方式取钱 * @Author shundong * @Date 2018/12/8 7:31 PM * @Version 1.0 **/ public class Bank { // 假设一个账户有1000块钱 static int money = 1000; // 柜台Counter取钱的方法 public synchronized void Counter(int money) {// 参数是每次取走的钱 Bank.money -= money;//取钱后总数减少 System.out.println("A取走了" + money + "还剩下" + (Bank.money)); } // ATM取钱的方法 public synchronized void ATM(int money) {// 参数是每次取走的钱 Bank.money -= money;//取钱后总数减少 System.out.println("B取走了" + money + "还剩下" + (Bank.money)); } }
(二)创建一个PersonA类
package com.shundong.day1; /** * @ClassName PersonA * @Description 用户A 在柜台取钱 每次 100 * @Author shundong * @Date 2018/12/8 7:31 PM * @Version 1.0 **/ public class PersonA extends Thread{ //创建一个银行对象 Bank bank; // 通过构造器传入银行对象,确保两个人进入的是一个银行 public PersonA(Bank bank) { this.bank = bank; } //重写run方法,在里面实现使用柜台取钱 @Override public void run() { while (Bank.money >= 100) { bank.Counter(100);// 每次取100块 try { sleep(100);// 取完休息0.1秒 } catch (InterruptedException e) { e.printStackTrace(); } } } }
(三)创建一个PersonB类
package com.shundong.day1; /** * @ClassName PersonB * @Description 用户B 在ATM 取款 每次200 * @Author shundong * @Date 2018/12/8 7:33 PM * @Version 1.0 **/ public class PersonB extends Thread { // 创建银行对象 Bank bank; // 通过构造器传入银行对象,确保两个人进入的是一个银行 public PersonB(Bank bank) { this.bank = bank; } // 重写run方法,在里面实现使用柜台取钱 @Override public void run() { while (Bank.money >= 200) { bank.ATM(200);// 每次取200块 try { sleep(100);// 取完休息0.1秒 } catch (InterruptedException e) { e.printStackTrace(); } } } }
(四)创建一个MainClass类 测试
package com.shundong.day1; /** * @ClassName MainClass * @Description 两个人AB通过一个账户A在柜台取钱和B在ATM机取钱 * @Author shundong * @Date 2018/12/8 7:35 PM * @Version 1.0 **/ public class MainClass { //for test public static void main(String[] args) { Bank bank = new Bank(); PersonA personA = new PersonA(bank); PersonB personB = new PersonB(bank); personA.start(); personB.start(); } }
运行MainClass类 结果:
四.示例三:龟兔赛跑问题
龟兔赛跑:20米 //只要为了看到效果,所有距离缩短了
要求:
1.兔子每秒0.5米的速度,每跑2米休息10秒,
2.乌龟每秒跑0.1米,不休息
3.其中一个跑到终点后另一个不跑了!
程序设计思路:
1.创建一个Animal动物类,继承Thread,编写一个running抽象方法,重写run方法,把running方法在run方法里面调用。
2.创建Rabbit兔子类和Tortoise乌龟类,继承动物类
3.两个子类重写running方法
4.本题的第3个要求涉及到线程回调。需要在动物类创建一个回调接口,创建一个回调对象
(一)创建Animal动物类
package com.shundong.dya2; /** * @ClassName Animal * @Description 抽象类 动物 * @Author shundong * @Date 2018/12/8 7:53 PM * @Version 1.0 **/ public abstract class Animal extends Thread { //赛道长度 public double length = 20.00; //抽象的 runing 子类只需要重写 该方法即可 public abstract void runing(); //父类重写的 run 只需要调用 runing即可 @Override public void run() { super.run(); while (length > 0) { runing(); } } //在需要回调数据的地方(两个子类需要),声明一个接口 public static interface Calltoback { public void win(); } //2.创建接口对象 public Calltoback calltoback; }
(二)创建Rabbit兔子类
package com.shundong.dya2; /** * @ClassName Rabbit * @Description 兔子的类 兔子每秒0.5米的速度,每跑2米休息10秒, * @Author shundong * @Date 2018/12/8 8:01 PM * @Version 1.0 **/ public class Rabbit extends Animal { //构造器为 此线程取名 public Rabbit() { setName("兔子"); } //重写 父类 动物类的 runing的 方法 @Override public void runing() { // 跑的距离 double dis = 0.5; length -= dis;//跑完后距离减少 if (length <= 0) { length = 0; System.out.println("兔子获得了胜利"); //给回调对象赋值,让乌龟不要再跑了 if (calltoback != null) { calltoback.win(); } } System.out.println("兔子跑了" + dis + "米,距离终点还有" + (int) length + "米"); if (length % 2 == 0) {// 两米休息一次 时间为 1s 10s太长了 该处为了 方便测试 try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
(三)创建Tortoise乌龟类
package com.shundong.dya2; /** * @ClassName Tortoise * @Description 乌龟类 * @Author shundong * @Date 2018/12/8 8:05 PM * @Version 1.0 **/ public class Tortoise extends Animal { // Thread的方法,给线程赋值名字 public Tortoise() { setName("乌龟"); } // 重写running方法,编写乌龟的奔跑操作 @Override public void runing() { // 跑的距离 double dis = 0.1; length -= dis; if (length <= 0) { length = 0; System.out.println("乌龟获得了胜利"); // 让兔子不要在跑了 回调函数 if (calltoback != null) { calltoback.win(); } } System.out.println("乌龟跑了" + dis + "米,距离终点还有" + (int) length + "米"); try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
(四)创建一个让动物线程停止的类,这里要实现回调接口
package com.shundong.dya2; /** * @ClassName LetOneStop * @Description 处理回调函数 * @Author shundong * @Date 2018/12/8 8:09 PM * @Version 1.0 **/ public class LetOneStop implements Animal.Calltoback { //动物对象 Animal animal; //传过来的 参数 不是乌龟就是兔子 public LetOneStop(Animal animal) { this.animal = animal; } //让线程停止的回调函数 @Override public void win() { //停止线程 animal.stop(); } }
(五)创建一个主方法调用类,
package com.shundong.dya2; /** * @ClassName MainClass * @Description 龟兔赛跑:20米 测试 * @Author shundong * @Date 2018/12/8 8:12 PM * @Version 1.0 **/ public class MainClass { //for test public static void main(String[] args) { //实例化乌龟和兔子 Tortoise tortoise = new Tortoise(); Rabbit rabbit = new Rabbit(); //回调方法的使用,谁先调用calltoback方法,另一个就不跑了 LetOneStop letOneStop1 = new LetOneStop(tortoise); rabbit.calltoback = letOneStop1;//让兔子的回调方法里面存在乌龟对象的值,可以把乌龟stop LetOneStop letOneStop2 = new LetOneStop(rabbit); tortoise.calltoback = letOneStop2;//让乌龟的回调方法里面存在兔子对象的值,可以把兔子stop //开始跑 tortoise.start(); rabbit.start(); } }
运行MainClass类 结果:
待续。。。。
Java多线程_复习(更新中!!)的更多相关文章
- Java多线程4:Thread中的静态方法
一.Thread类中的静态方法 Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可 ...
- Java多线程笔记[未更新完]
最近课上可摸鱼时间较多,因此并发开坑学习 本篇学习自Java多线程编程实战指南 目前进展:刚开坑,处于理解概念阶段 本篇学习自Java多线程编程实战指南 Q.进程和线程的区别 进程Process是程序 ...
- Java多线程_生产者消费者模式2
在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...
- 1.java多线程_实现线程的两种方式
1.java多线程基本知识 1.1.进程介绍 不管是我们开发的应用程序,还是我们运行的其他的应用程序,都需要先把程序安装在本地的硬盘上.然后找到这个程序的启动文件, 启动程序的时候,其实是电脑把当前的 ...
- java多线程2:Thread中的方法
静态方法: Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程". 为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作.下面 ...
- Java基础——集合(持续更新中)
集合框架 Java.util.Collection Collection接口中的共性功能 1,添加 booblean add(Object obj); 往该集合中添加元素,一次添加一个 boolea ...
- Java多线程_缓存对齐
1.什么是缓存对齐 当前的电脑中,数据存储在磁盘上,可以断电保存,但是读取效率较低.不断电的情况下,数据可以在内存中存储,相对硬盘效率差不多是磁盘的一万倍左右.但是运算时,速度最快的是直接缓存在CPU ...
- Java多线程_并发容器ConcurrentHashMap/CopyOnWriteArrayList/CopyOnWriteArraySet
ConcurrentHashMap HashMap是线程不安全的,可以使用Collections.synchronizedMap(map)把一个不安全的map变成安全的,但是这里可以直 ...
- Java多线程2:Thread中的实例方法
Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1 ...
随机推荐
- 【转贴】一次 JDBC 与 MySQL 因 “CST” 时区协商误解导致时间差了 14 或 13 小时的排错经历
原文:https://juejin.im/post/5902e087da2f60005df05c3d ------------------------------------------------- ...
- ATL右键文件菜单
自己写的小程序中用到的,网上资料相对还是毕竟全的,这里再整理下.毕竟我也不是很了解ATL,里面估计还是有不少问题的,就当作参考吧. 1.创建ATL工程,这个没什么好讲的. 我对COM组件没什么研究,这 ...
- koa 路由配置
Koa 路由 路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET.POST 等) 组成的,涉及到应用如何响应客户端对某个网站节点的访问. 通俗的讲:路由就是根据不 ...
- Java多线程——中断机制
前言:在Java多线程中,中断一直围绕着我们,当我们阅读各种关于Java多线程的资料.书籍时,“中断”一词总是会出现,笔者对其的理解也是朦朦胧胧,因此非常有必要搞清楚Java多线程的中断机制. 1.J ...
- docker 安装 mongodb
1.docker search mongo 2.docker pull mongo 3.//docker run -d --name mymongo -p 27017:27017 -v /home/h ...
- 8-过滤器Filter和监听器Listener
一.web监听器:监听特殊事件的发生1.监听实现步骤 a.写一个java类,实现特定的接口,重写相关方法 b.在web.xml中,牌配置 <listener> <listener-c ...
- loss函数和cost函数
loss函数指单个样本的预测值和真值的偏差 cost函数指整体样本的预测值和真值的偏差
- vc图像合成
本程序下载地址: 上一篇讲述了tiff格式图片拆分成多张图片, 这篇博客讲述如何把多张任意格式的图片合成为一张图片. 图像合成仍然需要借助Cximage图像库,合成函数为Mixfrom, 函数原型为: ...
- jQuery对象与DOM对象之间的转换(转)
原文:https://www.cnblogs.com/lsy0403/p/5907084.html 什么是DOM对象 使用JavaScript中的方法获取页面中的元素返回的对象就是dom对象.比如使用 ...
- Laravel 入口文件解读及生命周期
这里只贴index.php的代码, 深入了解的请访问 https://laravel-china.org/articles/10421/depth-mining-of-laravel-life- ...