在现实生活中有很多问题涉及到了多线程,可以说多线程与我们的生活息息相关
这里说几个很典型也是很多程序员包括书本所引用的例子:①火车站卖票问题 ②缓冲区缓冲问题 ③生产者消费者问题
这样的问题没有线程根本没有办法解决,但如果解决不好又会遇到很多混乱,下面请看代码。
public class TestThreadTrain {
public static void main(String[] args) {
Thread5 thread5=new Thread5();
Thread thread51 =new Thread(thread5);
Thread thread52 =new Thread(thread5);
Thread thread53 =new Thread(thread5);
thread51.start();
thread52.start();
thread53.start();
thread51.setPriority(Thread.MAX_PRIORITY);
}
};
class Thread5 implements Runnable{
private int count=5;//火车票的数量
public void run(){
for(int i=0;i<100;i++){
if(this.count>0){//表示还有票
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("现在卖出,还剩:"+--count);
}
}
}
}
火车站售票问题
这是一个很典型的火车站售票问题,由于不只有一个售票点,但是票数是有限的,也许有一个售票点正在售票的时候得到了总票数,而另一个点却刚好完成售票操作,那么这个售票点的票数就是有错误的,所以运行上面的代码会发现有的时候执行会发生最终票数为负数的情况。这是一个需要在多线程中解决的问题。
再看一个银行账户存款取款的问题
package com;
public class TestThreadBank {
private String name; //name
private double balance; //balance
public TestThreadBank(String name){
this.name=name;
this.balance=0;
}
public String getName(){
return name;
}
public double balance(){
return balance;
}
public void put(double value) //存款操作
{
if(value>0){
this.balance+=value;
}
}
public double get(double value){//取款操作
if(value>0){
if(value
this.balance-=value;
else{
value=this.balance;
this.balance=0;
}
return value;
}
return 0;
}
public static void main(String args[]){//主方法
TestThreadBank bank=new TestThreadBank("wang");
//TestThreadBank bank2=new TestThreadBank("xiang");
(new Save(bank, 100)).start();
(new Save(bank, 200)).start();
(new Fetch(bank, 300)).start();
}
}
class Save extends Thread{
private TestThreadBank countBank;
private double value;
public Save(TestThreadBank A,double value)//存款类
{
this.countBank=A;
this.value=value;
}
public void run(){
//synchronized (this.countBank) {
double howmach=this.countBank.balance();
this.countBank.put(value);
try{
sleep(1);
}catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println(this.countBank.getName()+"账户:现有"+howmach+"存入"+this.value+"余额"+this.countBank.balance());
//}
}
}
class Fetch extends Thread{
private TestThreadBank countBank;
private double value;
public Fetch(TestThreadBank A1,double value){
this.countBank=A1;
this.value=value;
}
public void run(){
//synchronized (this.countBank) {
double howmatch=this.countBank.balance();
System.out.println(this.countBank.getName()+"账户:现有"+howmatch+"取走"+this.countBank.get(value)+"余额"+this.countBank.balance());
try {
sleep(1);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
//}
}
我们执行完这个代码之后发现有很多的错误出现,比如说
wang账户:现有300.0取走300.0余额0.0
wang账户:现有0.0存入100.0余额0.0
wang账户:现有100.0存入200.0余额0.0
现在会发现出现了典型的数据不一致问题,由于在线程中运行时加入了线程睡眠,所以程序不管是开始运行还是运行结束都是未知的,所以我们的结果也是未知的。很有可能在线程执行的额时候发生了意外,导致了读脏数据。
这些是典型的数据不一致导致了线程执行时发生意外
再看一个的缓冲区问题,假设现在有一个缓冲区装置容量为1,有写入和写出操作两个线程,没次操作都只涉及到一个变量。
我们一般写的话就会出现下面这样的代码。
package com;
public class TestBuffer {
private int value;//这个值
//给它两个方法
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public static void main(String[] args) {
TestBuffer buffer=new TestBuffer();
new save1(buffer).start();
new receive(buffer).start();
}
}
//线程类 存内容
class save1 extends Thread{
//这个类里面有一个容器
private TestBuffer buffer;
public save1(TestBuffer buffer) {
this.buffer=buffer;
}
public void run(){
for(int i=0;i<5;i++){
this.buffer.setValue(i);
System.out.println("存入:"+i);
}
}
}
//取线程内容
class receive extends Thread{
//这个类里面有一个容器
private TestBuffer buffer;
public receive(TestBuffer buffer) {
this.buffer=buffer;
}
public void run(){
for(int i=0;i<5;i++){
System.out.println("取出:"+this.buffer.getValue());
}
}
}
而现在得到的结果是这样的
存入:0
存入:1
存入:2
存入:3
存入:4
取出:4
取出:4
取出:4
取出:4
取出:4
显然我们存进去的值并不是每一个都被取出来了,前面的数据都被覆盖了,那么有没有办法能存一个取一个呢?能不能保证这些存入和取出操作正常的运行呢?