大型网站过程,快速制作网站,如何做优品快报下的子网站,房地产公司网站开发文章目录 前言多线程的常见应用场景多线程使用的主要目的在于业务需求程序设计代码示例运行结果总结 前言
Java多线程程序设计到的知识#xff1a; 对同一个数量进行操作 对同一个对象进行操作 回调方法使用 线程同步#xff0c;死锁问题 线程通信 …
多线程的常见应用… 文章目录 前言多线程的常见应用场景多线程使用的主要目的在于业务需求程序设计代码示例运行结果总结 前言
Java多线程程序设计到的知识 对同一个数量进行操作 对同一个对象进行操作 回调方法使用 线程同步死锁问题 线程通信 …
多线程的常见应用场景
后台任务例如定时向大量100w以上的用户发送邮件异步处理例如发微博、记录日志等分布式计算
多线程使用的主要目的在于 吞吐量你做WEB容器帮你做了多线程但是他只能帮你做请求层面的。简单的说可能就是一个请求一个线程。或多个请求一个线程。如果是单线程那同时只能处理一个用户的请求。 伸缩性也就是说你可以通过增加CPU核数来提升性能。如果是单线程那程序执行到死也就利用了单核肯定没办法通过增加CPU核数来提升性能。
在java中每一个线程有一块工作内存区其中存放着被所有线程共享的主内存中的变量的值的拷贝。当线程执行时它在自己的工作内存中操作这些变量。
为了存取一个共享的变量一个线程通常先获取锁定并且清除它的工作内存区这保证该共享变量从所有线程的共享内存区正确地装入到线程的工作内存区当线程解锁时保证该工作内存区中变量的值协会到共享内存中。
当一个线程使用某一个变量时不论程序是否正确地使用线程同步操作它获取的值一定是由它本身或者其他线程存储到变量中的值。例如如果两个线程把不同的值或者对象引用存储到同一个共享变量中那么该变量的值要么是这个线程的要么是那个线程的共享变量的值不会是由两个线程的引用值组合而成。
一个变量时Java程序可以存取的一个地址它不仅包括基本类型变量、引用类型变量而且还包括数组类型变量。保存在主内存区的变量可以被所有线程共享但是一个线程存取另一个线程的参数或者局部变量时不可能的所以开发人员不必担心局部变量的线程安全问题。
业务需求
电影院新片首映观影人数大量增加为提高日营业额线下售票窗口由原单窗口调整为3窗口设计一段简单的程序模拟该售票过程。
程序设计
多线程场景下需考虑线程安全的问题避免多个线程争抢同一个资源导致业务逻辑出现错误。实现线程安全的方式有很多这里使用Java Lock 接口中的方法实现。
代码示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 测试类*/
public class DemoTest {public static void main(String[] args) {//窗口01new Thread(() - {while (true) {//售票并获取售票后的当前票余量int currentTickets TicketSource.saleTickets();//模拟售票员卖出一张票用时1秒waitProcess();//票已卖完if (currentTickets 0) break;}}, 01).start();//窗口02new Thread(() - {while (true) {int currentTickets TicketSource.saleTickets();waitProcess();if (currentTickets 0) break;}}, 02).start();//窗口03new Thread(() - {while (true) {int currentTickets TicketSource.saleTickets();waitProcess();if (currentTickets 0) break;}}, 03).start();}private static void waitProcess() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}/*** 电影票资源类*/
class TicketSource {//当前电影票余量private static int currentTickets 30;//加锁确保多线程场景下的线程安全private static final Lock lock new ReentrantLock();/*** 卖票** return 当前电影票余量*/public static int saleTickets() {lock.lock();try {if (currentTickets 0) {//模拟卖票currentTickets--;if (currentTickets 0) {//票余量为 0 停止售卖System.out.println(Thread.currentThread().getName() 窗口出票成功 当前票余量 currentTickets 今日票已卖完);} else {System.out.println(Thread.currentThread().getName() 窗口出票成功 当前票余量 currentTickets);}} else {//票余量为 0 停止售卖System.out.println(Thread.currentThread().getName() 窗口今日票已卖完);}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}return currentTickets;}}运行结果
D:\installPath\Java\jdk1.8.0_121\bin\java.exe -javaagent:D:\installPath\IntelliJ IDEA 2019.1.4\lib\idea_rt.jar64339:D:\installPath\IntelliJ IDEA 2019.1.4\bin
01窗口出票成功当前票余量29
02窗口出票成功当前票余量28
03窗口出票成功当前票余量27
01窗口出票成功当前票余量26
03窗口出票成功当前票余量25
02窗口出票成功当前票余量24
03窗口出票成功当前票余量23
01窗口出票成功当前票余量22
02窗口出票成功当前票余量21
02窗口出票成功当前票余量20
03窗口出票成功当前票余量19
01窗口出票成功当前票余量18
01窗口出票成功当前票余量17
02窗口出票成功当前票余量16
03窗口出票成功当前票余量15
02窗口出票成功当前票余量14
01窗口出票成功当前票余量13
03窗口出票成功当前票余量12
01窗口出票成功当前票余量11
03窗口出票成功当前票余量10
02窗口出票成功当前票余量9
03窗口出票成功当前票余量8
02窗口出票成功当前票余量7
01窗口出票成功当前票余量6
03窗口出票成功当前票余量5
02窗口出票成功当前票余量4
01窗口出票成功当前票余量3
01窗口出票成功当前票余量2
03窗口出票成功当前票余量1
02窗口出票成功当前票余量0 今日票已卖完
01窗口今日票已卖完
03窗口今日票已卖完Process finished with exit code 0总结
代码块锁是一个防止数据发生错误的一个重要手段。
对象的统一性是非常重要的这要想到对象的传入问题
要操作的对象只能new一次其他的操作都是对这个传入的对象进行的
才能保证数据一致性完整性和正确性。