- 先看一下java多线程资源竞争的案例
/* 当多个线程访问同一个变量时,这个变量被称为共享变量,而当多个线程操作同一个变量时,就会出现资源竞争的问题,
* 举例, 有个变量num为100, 每个线程对其的操作就是减去1(想想一下卖票系统,100个票,有三个售票员[三个线程]),有一个
* 在cpu哪里累死累活抢到了使用权,拿到了100,还没来的及去减1, 完了,cpu被第二只线程抢了过去,一看num还是100,然后执行了100-1
* num就这样变为了99,这时第一个cpu终于抢到了cpu的使用权,去吧num减1,这一减不要紧,num也变成了99,这样,100这支票被卖出去了两
* 此,那这问题就出现了,票卖重了,这是谁的锅? 或者当卖到最后一张票时,还很容易造成超卖现象
* */
import javax.sql.rowset.spi.SyncFactory;
public class Demo26Class implements Runnable {
private int num1;
Object obj = new Object();
Demo26Class(){
}
Demo26Class(int num){
this.num1 = num;
}
@Override
public void run() {
while (true) {
if (num1 > 0){
// 添加延迟时间,可以更好的看出资源竞争
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售出车票第" + num1-- + "张");
}
}
}
}
// 调用线程共享, 注意,资源竞争不是说创建很多对象,而是一个对象中的多个线程对资源的竞争,比如下面代码中objClass1的对象
// 而不是在new一个对象objClass2,然后再start
public class Demo27Class {
public static void main(String[] args) {
int num = 20;
Demo26Class objClass1 = new Demo26Class(num);
new Thread(objClass1, "售票车窗1").start();
new Thread(objClass1, "售票车窗2").start();
new Thread(objClass1, "售票车窗3").start();
}
}
执行结果:
售票车窗2售出车票第19张
售票车窗3售出车票第18张
售票车窗1售出车票第20张
售票车窗2售出车票第17张
售票车窗1售出车票第15张
售票车窗3售出车票第16张
售票车窗2售出车票第13张
售票车窗3售出车票第12张
售票车窗1售出车票第14张
售票车窗1售出车票第10张
售票车窗3售出车票第11张
售票车窗2售出车票第9张
售票车窗1售出车票第8张
售票车窗3售出车票第6张
售票车窗2售出车票第7张
售票车窗2售出车票第5张
售票车窗1售出车票第5张
售票车窗3售出车票第5张
售票车窗1售出车票第3张
售票车窗3售出车票第4张
售票车窗2售出车票第2张
售票车窗1售出车票第1张
售票车窗3售出车票第0张
售票车窗2售出车票第-1张
- 解决方案一:同步代码块 synchronized()
/* 当多个线程访问同一个变量时,这个变量被称为共享变量,而当多个线程操作同一个变量时,就会出现资源竞争的问题,
* 举例, 有个变量num为100, 每个线程对其的操作就是减去1(想想一下卖票系统,100个票,有三个售票员[三个线程]),有一个
* 在cpu哪里累死累活抢到了使用权,拿到了100,还没来的及去减1, 完了,cpu被第二只线程抢了过去,一看num还是100,然后执行了100-1
* num就这样变为了99,这时第一个cpu终于抢到了cpu的使用权,去吧num减1,这一减不要紧,num也变成了99,这样,100这支票被卖出去了两
* 此,那这问题就出现了,票卖重了,这是谁的锅? 或者当卖到最后一张票时,还很容易造成超卖现象
* */
import javax.sql.rowset.spi.SyncFactory;
public class Demo26Class implements Runnable {
private int num1;
Object obj = new Object();
Demo26Class(){
}
Demo26Class(int num){
this.num1 = num;
}
@Override
public void run() {
while (true) {
// obj 是一个对象
synchronized(obj){
if (num1 > 0){
// 添加延迟时间,可以更好的看出资源竞争
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售出车票第" + num1-- + "张");
}
}
}
}
}
执行结果:
售票车窗1售出车票第20张
售票车窗1售出车票第19张
售票车窗1售出车票第18张
售票车窗1售出车票第17张
售票车窗1售出车票第16张
售票车窗1售出车票第15张
售票车窗1售出车票第14张
售票车窗1售出车票第13张
售票车窗1售出车票第12张
售票车窗1售出车票第11张
售票车窗1售出车票第10张
售票车窗1售出车票第9张
售票车窗1售出车票第8张
售票车窗1售出车票第7张
售票车窗1售出车票第6张
售票车窗1售出车票第5张
售票车窗1售出车票第4张
售票车窗3售出车票第3张
售票车窗2售出车票第2张
售票车窗2售出车票第1张
- 解决方案二:同步函数 synchronized, 这里以静态方法演示
/* 当多个线程访问同一个变量时,这个变量被称为共享变量,而当多个线程操作同一个变量时,就会出现资源竞争的问题,
* 举例, 有个变量num为100, 每个线程对其的操作就是减去1(想想一下卖票系统,100个票,有三个售票员[三个线程]),有一个
* 在cpu哪里累死累活抢到了使用权,拿到了100,还没来的及去减1, 完了,cpu被第二只线程抢了过去,一看num还是100,然后执行了100-1
* num就这样变为了99,这时第一个cpu终于抢到了cpu的使用权,去吧num减1,这一减不要紧,num也变成了99,这样,100这支票被卖出去了两
* 此,那这问题就出现了,票卖重了,这是谁的锅? 或者当卖到最后一张票时,还很容易造成超卖现象
* */
import javax.sql.rowset.spi.SyncFactory;
public class Demo26Class implements Runnable {
private static int num1 = 20;
@Override
public void run() {
demoDef1();
}
public static synchronized void demoDef1(){
while (true) {
if (num1 > 0){
// 添加延迟时间,可以更好的看出资源竞争
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售出车票第" + num1-- + "张");
}
}
}
}
// 调用线程共享, 注意,资源竞争不是说创建很多对象,而是一个对象中的多个线程对资源的竞争,比如下面代码中objClass1的对象
// 而不是在new一个对象objClass2,然后再start
public class Demo27Class {
public static void main(String[] args) {
Demo26Class objClass1 = new Demo26Class();
new Thread(objClass1, "售票车窗1").start();
new Thread(objClass1, "售票车窗2").start();
new Thread(objClass1, "售票车窗3").start();
}
}
售票车窗1售出车票第20张
售票车窗1售出车票第19张
售票车窗1售出车票第18张
售票车窗1售出车票第17张
售票车窗1售出车票第16张
售票车窗1售出车票第15张
售票车窗1售出车票第14张
售票车窗1售出车票第13张
售票车窗1售出车票第12张
售票车窗1售出车票第11张
售票车窗1售出车票第10张
售票车窗1售出车票第9张
售票车窗1售出车票第8张
售票车窗1售出车票第7张
售票车窗1售出车票第6张
售票车窗1售出车票第5张
售票车窗1售出车票第4张
售票车窗1售出车票第3张
售票车窗1售出车票第2张
售票车窗1售出车票第1张
- 解决方案三:建立锁(推荐使用)
/* 当多个线程访问同一个变量时,这个变量被称为共享变量,而当多个线程操作同一个变量时,就会出现资源竞争的问题,
* 举例, 有个变量num为100, 每个线程对其的操作就是减去1(想想一下卖票系统,100个票,有三个售票员[三个线程]),有一个
* 在cpu哪里累死累活抢到了使用权,拿到了100,还没来的及去减1, 完了,cpu被第二只线程抢了过去,一看num还是100,然后执行了100-1
* num就这样变为了99,这时第一个cpu终于抢到了cpu的使用权,去吧num减1,这一减不要紧,num也变成了99,这样,100这支票被卖出去了两
* 此,那这问题就出现了,票卖重了,这是谁的锅? 或者当卖到最后一张票时,还很容易造成超卖现象
* */
import javax.sql.rowset.spi.SyncFactory;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo26Class implements Runnable {
private static int num1 = 20;
// 创建一把锁
Lock lock1 = new ReentrantLock();
@Override
public void run() {
while (true) {
// 上锁
lock1.lock();
if (num1 > 0){
// 添加延迟时间,可以更好的看出资源竞争
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售出车票第" + num1-- + "张");
}
// 解锁
lock1.unlock();
}
}
}
// 调用线程共享, 注意,资源竞争不是说创建很多对象,而是一个对象中的多个线程对资源的竞争,比如下面代码中objClass1的对象
// 而不是在new一个对象objClass2,然后再start
public class Demo27Class {
public static void main(String[] args) {
Demo26Class objClass1 = new Demo26Class();
new Thread(objClass1, "售票车窗1").start();
new Thread(objClass1, "售票车窗2").start();
new Thread(objClass1, "售票车窗3").start();
}
}
执行结果:
售票车窗1售出车票第20张
售票车窗1售出车票第19张
售票车窗1售出车票第18张
售票车窗1售出车票第17张
售票车窗1售出车票第16张
售票车窗1售出车票第15张
售票车窗1售出车票第14张
售票车窗1售出车票第13张
售票车窗1售出车票第12张
售票车窗1售出车票第11张
售票车窗1售出车票第10张
售票车窗1售出车票第9张
售票车窗1售出车票第8张
售票车窗1售出车票第7张
售票车窗1售出车票第6张
售票车窗1售出车票第5张
售票车窗1售出车票第4张
售票车窗1售出车票第3张
售票车窗1售出车票第2张
售票车窗1售出车票第1张