假如有十张票,现在需要三个窗口(线程)卖,代码如下:
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(); } }
相关推荐
本文主要介绍了java高并发写入用户信息到数据库的几种方法,具有很好的参考价值。下面跟着小编一起来看下吧
在进行并发编程时,如果希望通过多线程执行任务让程序运行的更快,会面临非常多的挑战,比如上下文切换的问题,死锁的问题,以及受限于硬件和软件的资源限制问题,本章会介绍几种并发编程的挑战,以及解决方案。
java并发编程 基础知识,守护线程与线程, 并行和并发有什么区别? 什么是上下文切换? 线程和进程区别 什么是线程和进程? 创建线程有哪几种方式?,如何避免线程死锁 线程的 run()和 start()有什么区别? 什么是 ...
带着你了解了高并发系统设计的三种通用方法:Scale-out、缓存和异步。...了解了缓存使用的几种策略,以及每种策略适用的使用场景是怎样的。 了解了消息队列在高并发系统设计中起到的作用,以及一些注意事项,
Java并发编程的4种风格:Threads,Executors,ForkJoin和Actors 我们生活在一个事情并行发生的世界。自然地,我们编写的程序也反映了这个特点,它们可以并发的执行。当然除了Python代码(译者注:链接里面讲述...
要完全理解interface是为什么,用多线程又有几种常用的编程模型。 4。理解了语言的特性是为什么了之后,就可以试着上升到设计这个层次,毕竟学习语言是要用的。目前比较好的开发模式是采用自定向
一、总论:在JDK中提供了几种并发工具类 1)CountDownLatch(同步倒数计数器:等待多线程(或者多步骤)完成) 2)CyclicBarrier(循环屏障:同步屏障) 3)Semaphore(信号量:控制并发进程数) 主要参考...
在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会面临非常多的挑战,比如上下文切换的问题、死锁的问题,以及受限于硬件和软件的资源限制问题,本章会介绍几种并发编程的挑战以及解决方案。
目录java并发编程三剑客思维导图CountDownLatch用法构造器以及方法构造器主要方法使用方法CyclicBarrier用法构造器以及主要方法构造器主要方法使用方法Semaphore用法构造器和主要方法构造器主要方法使用方法三种辅助...
在进行并发编程时,如果希望通过多线程执行任务让程序运行的更快,会面临非常多的挑战,比如上下文切换的问题,死锁的问题,以及受限于硬件和软件的资源限制问题,本章会介绍几种并发编程的挑战,以及解决方案。
最近笔者正好有所涉及,鉴于此,结合开发中的案例说明一下几种定时任务的 退出 。 需求说明 :定时更新正在生成的文件大小和状态【进行中、失败、完成】,如果文件生成完成,则退出【CoderBaby】 调度可以用 ...
1.使用new Thread()创建线程的弊端: 每次通过new Thread()创建对象...可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。 提供定时执行、定期执行、单线程、并发数控制等功能。
高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4 高并发编程第三阶段13讲 一个JNI程序的编写,通过Java去调用C,C++程序.mp4 高并发编程第三阶段14讲 Unsafe中的方法使用,一半是...
里面是自己收藏的几篇关于线程的文档资料,大家可以看看哈
Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run Anywhere): Java的代码可以在不同的平台上运行,只需编写一次代码,就可以在任何支持Java的设备上执行。这得益于Java虚拟机(JVM),它充当了...
java多线程设计模式,附源码中文教程,java并发核心编程,JAVA线程池原理以及几种线程池类型介绍
java_各个Map的区别 ConcurrentHashMap 支持检索的完全并发和更新的所期望可调整并发的哈希表。(线程安全)此类遵守与 Hashtable 相同的功能规范,并且包括对应于 Hashtable 的每个方法的方法版本。不过,尽管所有...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
并发——在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行——源自百度百科在并发编程中,我们需要...