当我们开启多个线程任务的时候,会发现他们会读取同一个数据,导致出现线程安全的问题。
这里使用实现接口的方式开启多个线程。
**
*
* @author jianyeli
*/
public class Runnableimpl implements Runnable {
public int ticket= 100;
@Override
//设置线程任务
public void run() {
while(true){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"正在卖---->"+ticket+"张票");
ticket--;
}
}
}
}
public class TestRunnableimpl1 {
public static void main(String[] args) {
Runnableimpl t = new Runnableimpl();
Thread m1 = new Thread(t);
Thread m2 = new Thread(t);
Thread m3 = new Thread(t);
//开启多个线程任务
m1.start();
m2.start();
m3.start();
}
}
以下是部分结果
出现执行线程时读取的数据相同
Thread-0正在卖---->100张票
Thread-1正在卖---->100张票
Thread-1正在卖---->97张票
Thread-1正在卖---->96张票
Thread-1正在卖---->95张票
Thread-1正在卖---->94张票
Thread-1正在卖---->93张票
Thread-1正在卖---->92张票
Thread-1正在卖---->91张票
Thread-1正在卖---->90张票
Thread-1正在卖---->89张票
Thread-1正在卖---->88张票
解决线程安全问题的第一种方式:同步代码块,也是同步锁,对象监视器,使用的时候创建一个对象。锁的作用锁住代码块,线程执行的时候只能执行一次。
Synchronized(同步锁{
需要同步操作的代码;
}
/**
*
* @author jianyeli
*/
public class Runnableimpl implements Runnable {
public int ticket= 100;
Object j = new Object();
@Override
public void run() {
while(true){
synchronized(j){
if(ticket>0){
//提高线程安全问题出现的概率,让程序睡眠
try{
Thread.sleep(10, 10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖---->"+ticket+"张票");
ticket--;
}
}
}
}
}
public class TestRunnableimpl1 {
public static void main(String[] args) {
Runnableimpl t = new Runnableimpl();
Thread m1 = new Thread(t);
Thread m2 = new Thread(t);
Thread m3 = new Thread(t);
//开启多个线程任务
m1.start();
m2.start();
m3.start();
}
}
以下是部分结果
Thread-0正在卖---->100张票
Thread-0正在卖---->99张票
Thread-0正在卖---->98张票
Thread-0正在卖---->97张票
Thread-0正在卖---->96张票
Thread-0正在卖---->95张票
Thread-2正在卖---->94张票
Thread-2正在卖---->93张票
Thread-2正在卖---->92张票
Thread-2正在卖---->91张票
Thread-2正在卖---->90张票
Thread-2正在卖---->89张票
Thread-2正在卖---->88张票
Thread-2正在卖---->87张票
Thread-2正在卖---->86张票