卖票类:
public class ThreadSafe implements Runnable{
private int ticket=100;
@Override
public void run() {
while(ticket<=100&&ticket>0){
try{
Thread.sleep(100);
}
catch (Exception e){
e.printStackTrace();
}
System.out.println("线程:"+Thread.currentThread().getName()+"取得票号为-----"+ticket--);
}
}
}
购票类:
import com.one.ThreadSafe;
public class ThreadSafeTest {
public static void main(String[] args) {
ThreadSafe threadSafe=new ThreadSafe();
Thread thread1=new Thread(threadSafe,"线程1");
thread1.start();
Thread thread2=new Thread(threadSafe,"线程2222");
thread2.start();
}
}
线程:线程2222取得票号为-----100
线程:线程1取得票号为-----99
线程:线程2222取得票号为-----98
线程:线程1取得票号为-----97
线程:线程2222取得票号为-----96
线程:线程1取得票号为-----95
线程:线程2222取得票号为-----93
线程:线程1取得票号为-----94
线程:线程1取得票号为-----92
线程:线程2222取得票号为-----91
线程:线程1取得票号为-----90
线程:线程2222取得票号为-----89
线程:线程1取得票号为-----88
线程:线程2222取得票号为-----87
线程:线程1取得票号为-----86
线程:线程2222取得票号为-----85
线程:线程1取得票号为-----84
线程:线程2222取得票号为-----83
线程:线程1取得票号为-----82
线程:线程2222取得票号为-----81
线程:线程2222取得票号为-----80
线程:线程1取得票号为-----79
线程:线程1取得票号为-----78
线程:线程2222取得票号为-----77
线程:线程2222取得票号为-----76
线程:线程1取得票号为-----75
线程:线程1取得票号为-----74
线程:线程2222取得票号为-----73
线程:线程1取得票号为-----72
线程:线程2222取得票号为-----71
线程:线程1取得票号为-----70
线程:线程2222取得票号为-----69
线程:线程2222取得票号为-----68
线程:线程1取得票号为-----67
线程:线程2222取得票号为-----66
线程:线程1取得票号为-----65
线程:线程1取得票号为-----63
线程:线程2222取得票号为-----64
线程:线程1取得票号为-----62
线程:线程2222取得票号为-----61
线程:线程1取得票号为-----60
线程:线程2222取得票号为-----59
线程:线程1取得票号为-----58
线程:线程2222取得票号为-----57
线程:线程2222取得票号为-----55
线程:线程1取得票号为-----56
线程:线程1取得票号为-----54
线程:线程2222取得票号为-----53
线程:线程2222取得票号为-----51
线程:线程1取得票号为-----52
线程:线程2222取得票号为-----49
线程:线程1取得票号为-----50
线程:线程2222取得票号为-----48
线程:线程1取得票号为-----47
线程:线程1取得票号为-----46
线程:线程2222取得票号为-----45
线程:线程2222取得票号为-----43
线程:线程1取得票号为-----44
线程:线程1取得票号为-----42
线程:线程2222取得票号为-----41
线程:线程1取得票号为-----40
线程:线程2222取得票号为-----39
线程:线程1取得票号为-----38
线程:线程2222取得票号为-----37
线程:线程2222取得票号为-----35
线程:线程1取得票号为-----36
线程:线程2222取得票号为-----34
线程:线程1取得票号为-----33
线程:线程2222取得票号为-----32
线程:线程1取得票号为-----31
线程:线程2222取得票号为-----30
线程:线程1取得票号为-----29
线程:线程2222取得票号为-----28
线程:线程1取得票号为-----27
线程:线程2222取得票号为-----26
线程:线程1取得票号为-----25
线程:线程1取得票号为-----24
线程:线程2222取得票号为-----23
线程:线程2222取得票号为-----21
线程:线程1取得票号为-----22
线程:线程2222取得票号为-----20
线程:线程1取得票号为-----19
线程:线程2222取得票号为-----18
线程:线程1取得票号为-----17
线程:线程2222取得票号为-----16
线程:线程1取得票号为-----15
线程:线程2222取得票号为-----14
线程:线程1取得票号为-----13
线程:线程2222取得票号为-----12
线程:线程1取得票号为-----11
线程:线程1取得票号为-----10
线程:线程2222取得票号为-----9
线程:线程2222取得票号为-----7
线程:线程1取得票号为-----8
线程:线程2222取得票号为-----5
线程:线程1取得票号为-----6
线程:线程1取得票号为-----4
线程:线程2222取得票号为-----3
线程:线程2222取得票号为-----1
线程:线程1取得票号为-----2
Process finished with exit code 0
购票类中,在Thread实例化对象时不定义线程名就会出现两条线程购得同一张票,但是定义了线程名后就不会出现上述情况(即定义 线程1 和 线程2222)
建议你多运行几次,或者增大循环次数。
存在线程安全问题,并不是一定会出现线程不安全现象,跟cpu有关,每次的结果都不太一样。
这个与线程名称无关,你可以删除Thread.sleep(100);语句,或者睡眠时间小一点,可能就出现重复的了,关键是需要使用同步语句块进行控制。
synchronized (this){
}
这个本身就是不安全的 俩线程各自跑
上锁,实现互斥访问
不关线程名的事哦,只是你加了sleep导致出现的几率变低而已,其实还是存在线程安全问题的
Thread.sleep(100);
最好就是加上锁
public class ThreadSafe implements Runnable{
private int ticket=100;
@Override
public void run() {
while(ticket<=100&&ticket>0){
synchronized (this){
try{
Thread.sleep(100);
}
catch (Exception e){
e.printStackTrace();
}
System.out.println("线程:"+Thread.currentThread().getName()+"取得票号为-----"+ticket--);
}
}
}
}