一.相关知识:
Java多线程程序设计到的知识:
(一)对同一个数量进行操作
(二)对同一个对象进行操作
(三)回调方法使用
(四)线程同步,死锁问题
(五)线程通信
等等
二.示例一:三个售票窗口同时出售20张票;
程序分析:1.票数要使用同一个静态值
2.为保证不会出现卖出同一个票数,要java多线程同步锁。
设计思路:1.创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖完!
2.创建主方法调用类
(一)创建一个站台类,继承Thread
package com.xykj.threadStation;
public class Station extends Thread {
// 通过构造方法给线程名字赋值
public Station(String name) {
super(name);// 给线程名字赋值
}
// 为了保持票数的一致,票数要静态
static int tick = 20;
// 创建一个静态钥匙
static Object ob = "aa";//值是任意的
// 重写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();
}
}
}
}
(二)创建主方法调用类
package com.xykj.threadStation;
public class MainClass {
/**
* java多线程同步锁的使用
* 示例:三个售票窗口同时出售10张票
* */
public static void main(String[] args) {
//实例化站台对象,并为每一个站台取名字
Station station1=new Station("窗口1");
Station station2=new Station("窗口2");
Station station3=new Station("窗口3");
// 让每一个站台对象各自开始工作
station1.start();
station2.start();
station3.start();
}
}
程序运行结果:
窗口2卖出了第20张票
窗口3卖出了第19张票
窗口1卖出了第18张票
窗口2卖出了第17张票
窗口3卖出了第16张票
窗口1卖出了第15张票
窗口1卖出了第14张票
窗口2卖出了第13张票
窗口3卖出了第12张票
窗口2卖出了第11张票
窗口1卖出了第10张票
窗口3卖出了第9张票
窗口2卖出了第8张票
窗口3卖出了第7张票
窗口1卖出了第6张票
窗口2卖出了第5张票
窗口1卖出了第4张票
窗口3卖出了第3张票
窗口3卖出了第2张票
窗口1卖出了第1张票
票卖完了
可以看到票数是不会有错的!
三.示例二:两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!
程序分析:钱的数量要设置成一个静态的变量。两个人要取的同一个对象值
(一)创建一个Bank类
/**两个人AB通过一个账户(2000元)
* A在柜台取钱和
* B在ATM机取钱!
* A一次取出100员,B一次取出200元,直到全部取出。
* Created by FXY on 2018/6/29.
*/
public class Bank {
public static int money = 2000;
public void withdrawMoney(int money , String equipment,String name) {
synchronized (this) { //加锁同步
if (equipment.endsWith("counter")&& Bank.money>=money) {
Bank.money -= money;
System.out.println(name+"在" + equipment + "取走了" + money + "还剩下" + Bank.money);
}
if(equipment.endsWith("atm")&& Bank.money>=money){
Bank.money -= money;
System.out.println(name+"在" + equipment + "取走了" + money + "还剩下" + Bank.money);
}
}
}
}
二)创建一个PersonA类
/**
* Created by FXY on 2018/6/29.
*/
public class PersionA extends Thread{
Bank bank;
// 通过构造器传入银行对象,确保两个人进入的是一个银行
public PersionA(Bank bank) {
this.bank = bank;
setName("counter");//给线程命名
}
@Override
public void run(){
while (Bank.money>=100){
bank.withdrawMoney(100,"counter",getName());
try {
sleep(1000);// 取完休息1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(三)创建一个PersonB类
/**
* Created by FXY on 2018/6/29.
*/
public class PersionB extends Thread{
Bank bank;
// 通过构造器传入银行对象,确保两个人进入的是一个银行
public PersionB(Bank bank) {
this.bank = bank;
setName("atm");
}
@Override
public void run() {
while(Bank.money>=200){
bank.withdrawMoney(200,"atm",getName());
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(四)创建主方法的调用类
public class MainClass {
/**
* 两个人AB通过一个账户A在柜台取钱和B在ATM机取钱
* */
public static void main(String[] args) {
// 实力化一个银行对象
Bank bank = new Bank();
// 实例化两个人,传入同一个银行的对象
PersonA pA = new PersonA(bank);
PersonB pB = new PersonB(bank);
// 两个人开始取钱
pA.start();
pB.start();
}
}
运行结果:
counter在counter取走了100还剩下1900
atm在atm取走了200还剩下1700
counter在counter取走了100还剩下1600
atm在atm取走了200还剩下1400
counter在counter取走了100还剩下1300
atm在atm取走了200还剩下1100
atm在atm取走了200还剩下900
counter在counter取走了100还剩下800
atm在atm取走了200还剩下600
counter在counter取走了100还剩下500
counter在counter取走了100还剩下400
atm在atm取走了200还剩下200
atm在atm取走了200还剩下0
可以看到取完就停止运行了。
今天就写了这俩例子,只要理解了,其他的就简单了!!!!!!
还有好几种例子,引用自此处
https://blog.youkuaiyun.com/wenzhi20102321/article/details/52524545