JAVA并发控制的几种办法
程序员文章站
2022-07-12 20:15:34
...
假如有十张票,现在需要三个窗口(线程)卖,代码如下:
package com.test.runnable; class MyThread implements Runnable { private int ticket = 10; public void run() { while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000l); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
输出结果为:
ticket = 10
ticket = 9
ticket = 8
ticket = 7
ticket = 7
ticket = 7
ticket = 6
ticket = 5
ticket = 6
ticket = 4
ticket = 4
ticket = 3
ticket = 2
ticket = 1
ticket = 2
可以发现不止卖 了十张,所以要进行并发控制。
第一种办法,采用同步关键字
package com.test.runnable; class MyThread implements Runnable { private int ticket = 10; synchronized public void run() { while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
可以发现输出结果为:
ticket = 10
ticket = 9
ticket = 8
ticket = 7
ticket = 6
ticket = 5
ticket = 4
ticket = 3
ticket = 2
ticket = 1
这样多个窗口卖票,就能正确了,
2.也可以采用原子变量
package com.test.runnable; import java.util.concurrent.atomic.AtomicInteger; class MyThread implements Runnable { private AtomicInteger ticket = new AtomicInteger(10); synchronized public void run() { while (ticket.get() > 0) { System.out.println("ticket = " + ticket.getAndAdd(-1)); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
3.采用信号量Semaphore
package com.test.runnable; import java.util.concurrent.Semaphore; class MyThread implements Runnable { final Semaphore semp = new Semaphore(1); private int ticket = 10; public void run() { // 获取许可 try { semp.acquire(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } // 访问完后,释放 semp.release(); } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
4.采用Lock
package com.test.runnable; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class MyThread implements Runnable { private Lock myLock = new ReentrantLock(); // 执行操作所需的锁对象 private int ticket = 10; public void run() { myLock.lock(); while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } // 访问完后,释放 myLock.unlock(); } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
5.但不能采用volatile关键字,因为线程内变量的值更新依赖原值。
package com.test.runnable; class MyThread implements Runnable { //private volatile int ticket = 10; private volatile int ticket = 10; public void run() { while (ticket > 0) { System.out.println("ticket = " + ticket--); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
上一篇: 线程同步辅助类semaphore笔记
下一篇: 记两次踩到的坑-Long类型赋值与比较