当前位置: 首页 > news >正文

做国内电影网站赚钱不2022今日最新军事新闻

做国内电影网站赚钱不,2022今日最新军事新闻,宜昌手机网站制作,江苏网站建设目录 线程安全 1.1 概述 1.2 案例分析 1.3 解决线程安全问题 1.3.1 使用synchronized关键字 1.3.1.1 同步代码块 1.3.1.2 同步方法 1.3.2 使用Lock锁 1.3.2.1 概述 代码示例: 1.4 线程安全的类 1.4.1 非线程安全集合转换成线程安全集合 1.5 总结 …

目录

线程安全

1.1 概述 

1.2 案例分析 

1.3 解决线程安全问题

1.3.1 使用synchronized关键字

1.3.1.1 同步代码块 

1.3.1.2 同步方法

1.3.2 使用Lock锁

1.3.2.1 概述 

代码示例:

1.4 线程安全的类

1.4.1 非线程安全集合转换成线程安全集合 

1.5 总结


线程安全

1.1 概述 

        指如果有多个线程在同时运行,而这些线程可能会同时运行某段代码,程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全。

1.2 案例分析 

那什么情况下会导致【线程不安全】呢?看如下案例:

假设:有三家电影院,卖票形式分别为以下A、B、C三种。

思考:哪一种卖票形式会出现问题呢?

  • 第1种:开一个窗口,卖100张票,不会出现问题,单线程程序不存在线程安全问题。
  • 第2种:开三个窗口,但是每个窗口票的号码不冲突,也不会出现问题,属于线程安全。
  • 第3种:开三个窗口,但是每个窗口票的号码一样。如果1,2,3三个窗口访问同一张票,那进入的结果和返回的结果很有可能不一致。这就出现了线程安全问题。

结论:

        买票出现了线程安全问题,可能会出现重复的票和不存在的票,但是线程安全问题是不允许出现的。 

1.3 解决线程安全问题

那怎么解决线程安全问题呢?

        我们可以让一个线程在访问共享数据的时候,无论是否失去了CPU的执行权,让其他的线程只能等待,等待当前线程买完票,其他线程在进行买票。保证同时只有一个线程在买票

1.3.1 使用synchronized关键字

        在Java中,synchronized是一个关键字,用于控制多个线程对 对象或方法 的访问。当一个代码块被标记为synchronized时,只允许一个线程在同一时间执行该代码块。这样做是为了防止并发访问和潜在的数据损坏或不一致。该关键字可以使用在同步代码块或者同步方法用来解决线程安全问题。

1.3.1.1 同步代码块 

         一个同步代码块一次只允许一个线程进入,并确保它完成执行后其他线程才能进入。这是通过使用与同步代码块关联的对象的内在锁(或监视器)来实现的。

格式:
       synchronized(锁对象){
           可能会出现线程安全问题的代码(访问了共享数据的代码)
       }

        

注意事项:

        1.同步代码块中的锁对象,可以使用任意的对象。

        2.必须保证多个线程使用的锁对象是同一个。

        3.锁对象作用:把同步代码块锁住,只让一个线程在同步代码块中执行。

代码示例: 

RunnableImpl.java:多线程的实现类

package com.zhy.multiplethread;public class RunnableImpl implements Runnable{/*** 共享票数*/private int ticket = 10;/*** 设置线程任务:卖票*/@Overridepublic void run() {//使用死循环,让卖票操作重复执行while (true){//同步代码块,保证每次只有一个线程占用锁对象synchronized (this){//当存在余票时,进行卖票操作if (ticket > 0){//为了表示卖票需要时间,暂停10毫秒try {Thread.sleep(10);}catch (InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " 正在卖第 " + ticket + "张票");ticket--;}}//出了同步代码块,归还锁对象,供线程重新抢占}}
}

TestThread.java:线程测试类

package com.zhy.multiplethread;public class TestThread {public static void main(String[] args) {RunnableImpl impl = new RunnableImpl();Thread t1 = new Thread(impl);Thread t2 = new Thread(impl);Thread t3 = new Thread(impl);//开启3个线程一起抢夺CPU的执行权,谁抢到谁执行t1.start();t2.start();t3.start();}
}

输出结果:多个线程共同抢占CPU进行卖票操作,不会出现线程安全问题。

1.3.1.2 同步方法

        当一个方法被声明为synchronized时,即使有多个线程同时访问该方法,也只允许一个线程执行。在这种情况下使用的锁是调用该方法的对象实例。  

格式:
        修饰符 synchronized 返回值类型 方法名(参数列表){
                可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

        

使用步骤:

        1.把访问了共享数据的代码抽取出来,放到一个方法中。

        2.在方法上添加synchronized修饰符

代码示例:

RunnableImpl.java:多线程的实现类 

package com.zhy.multiplethread;public class RunnableImpl implements Runnable{/*** 共享票数*/private int ticket = 10;/*** 设置线程任务:卖票*/@Overridepublic void run() {//使用死循环,让卖票操作重复执行while (true){payTicket();}}/*** 同步方法:卖票*/public synchronized void payTicket(){//当存在余票时,进行卖票操作if (ticket > 0){//为了表示卖票需要时间,暂停10毫秒try {Thread.sleep(10);}catch (InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " 正在卖第 " + ticket + "张票");ticket--;}}
}

结论:

        通过使用synchronized关键字,我们可以确保在多线程环境中共享资源的安全访问。

1.3.2 使用Lock锁

1.3.2.1 概述 

        java.util.concurrent.locks.Lock接口:实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作。 

Lock接口中的方法:
       void lock():获取锁
       void unlock():释放锁

        

实现类:

        java.util.concurrent.locks.ReentrantLock implements Lock接口

        

使用步骤:

        1.在成员位置创建一个ReentrantLock对象。

        2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁。

        3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁。一般放在finally里面执行。

代码示例:

RunnableImpl.java:多线程实现类

package com.zhy.multiplethread;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class RunnableImpl implements Runnable{/*** 共享票数*/private int ticket = 10;Lock l = new ReentrantLock();/*** 设置线程任务:卖票*/@Overridepublic void run() {//使用死循环,让卖票操作重复执行while (true){//获取锁:当存在余票时,进行卖票操作l.lock();try {if (ticket > 0) {//为了表示卖票需要时间,暂停10毫秒Thread.sleep(10);System.out.println(Thread.currentThread().getName() + " 正在卖第 " + ticket + "张票");ticket--;}}catch (InterruptedException e){e.printStackTrace();}finally {//释放锁:为了避免忘记释放或者出现异常,造成死锁,该操作放在finally中执行l.unlock();}}}
}

结论:

        同步保证了只能有一个线程在同步中执行共享数据,保证率安全,但是程序频繁的判断锁、获取锁、释放锁、程序的效率会降低。

1.4 线程安全的类

        如果一个类,所有的方法都是有synchronized修饰的,那么该类就叫做线程安全的类。保证同一时间,只有一个线程能够进入 这种类的一个实例 的去修改数据,进而保证了这个实例中的数据的安全,不会同时被多个线程修改而变成脏数据。

  • 操作集合的线程安全的类:Vector,Hashtable
  • 操作字符串的线程安全的类:StringBuffer

1.4.1 非线程安全集合转换成线程安全集合 

        ArrayList是非线程安全的,如果多个线程可以同时进入一个ArrayList对象的add/remove方法。那会造成什么后果呢,我们先看一个案例。 

场景:

        定义一个List集合,初始化5个元素。定义一个增加线程(往集合的头部持续插入1000个元素)和减少线程(从集合的头部持续移除1000个元素)同时操作该集合,我们最终想要的效果是:增加和减少的次数一致,最终集合内的元素仍然是初始化的元素。

代码示例:

package com.zhy.multiplethread;import com.zhy.thread.RunnableImpl;import java.util.ArrayList;
import java.util.List;public class TestThread {public static void main(String[] args) {//初始化List集合List<Integer> nonThreadSafeList = new ArrayList<Integer>();for (int i = 0; i < 5; i++){nonThreadSafeList.add(i + 3);}System.out.println("初始化List集合:" + nonThreadSafeList);//验证:使用两个线程同时往集合中插入1000个元素,在删除1000个元素int n = 1000;Thread[] addThreads = new Thread[n];Thread[] reduceThreads = new Thread[n];//将所有 增加线程 加入到addThreads数组中for (int i = 0; i < n; i++){Thread addThread = new Thread(){@Overridepublic void run() {nonThreadSafeList.add(0,1);try {//暂停1000毫秒,给其他线程抢占CPU的时间Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}};addThread.start();addThreads[i] = addThread;}//将所有 减少线程 加入到reduceThreads数组中for (int i = 0; i < n; i++){Thread reduceThread = new Thread(new RunnableImpl(){@Overridepublic void run() {if (nonThreadSafeList.size() > 0){nonThreadSafeList.remove(0);}try {//暂停1000毫秒,给其他线程抢占CPU的时间Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}});reduceThread.start();reduceThreads[i] = reduceThread;}//等待所有增加线程执行完成for (Thread addThread : addThreads){try {//将 增加线程 加入到主线程中addThread.join();}catch (InterruptedException e){e.printStackTrace();}}//等待所有 减少线程 执行完成for (Thread reduceThread : reduceThreads){try {//将 减少线程 加入到主线程中reduceThread.join();}catch (InterruptedException e){e.printStackTrace();}}//所有增加线程 和 减少线程 执行完毕后,List集合中的数据:正确应该为初始数据System.out.println("所有增加线程 和 减少线程 执行完毕后,List集合中的数据:" + nonThreadSafeList);}
}

输出结果:

        使用非线程安全的集合进行多线程处理,很显然最终的结果并不是我们想要的,出现了null的元素,且集合内的元素也不是初始化的元素。 

注:并不是每一次执行都会出现错误的结果,多执行几次,会发现执行结果并不一致。 

那如何把非线程安全的集合转换成线程安全的呢?  

        以ArrayList为例,使用Collections工具类中的synchronizedList,可以把ArrayList转换为线程安全的List。 

源码:

        public static <T> List<T> synchronizedList(List<T> list) ;

        

使用:Collections.synchronizedList(list);

        改造上述代码,变成线程安全,只需加入如下代码,然后将多线程中操作的集合换成转换后的集合即可:

        //将List转换成线程安全的类List<Integer> threadSafeList = Collections.synchronizedList(nonThreadSafeList);

 最终的执行结果如下,执行多次,结果一致。


        与此类似的,还有HashSet,LinkedList,HashMap等等非线程安全的类,具体类型如下,都可以通过Collections工具类转换为线程安全的


1.5 总结

        在多线程中,线程安全问题是不允许被出现的。所以我们在使用多线程时,对于共享数据,可以通过synchronized关键字和Lock锁来处理,保证线程安全。 synchronized使用简单但灵活性较差;而Lock是一个更灵活的同步方式,可以实现更复杂的同步需求,但需要手动管理锁的获取和释放。在实际开发中,可以根据具体需求进行选择。

http://www.ritt.cn/news/22495.html

相关文章:

  • 《原始传奇》官方网站上海广告公司排名
  • 昆明网站建设费用广东网站seo策划
  • 做网站大概需要几个人网站建设的六个步骤
  • 云南做商城网站多少钱权重查询站长工具
  • asp.net课程网站模板下载西安关键词优化服务
  • 做中小型网站最好的架构武汉seo搜索引擎
  • 免费网站主机推广策略都有哪些
  • 2016做网站深圳网站建设资讯
  • 龙岩市住房与城乡建设局网站图片优化网站
  • 网站建设优化服务报价最近一周的新闻
  • 如何做点对点视频网站天津seo博客
  • 西安网站网络营销上海网络营销有限公司
  • 企业网站的基本要素seo优化技术教程
  • 桂林生活网二手市场seo网站关键词优化哪家好
  • 做直播网站赚钱吗1688如何搜索关键词排名
  • 建设网站视频教程广告行业怎么找客户
  • wordpress做论坛seo综合查询是啥意思
  • 如何编辑网站内容东莞快速排名
  • 做时时的网站qq群推广链接
  • 阿里云网站建设视频成都网站关键词排名
  • 微信上做任务让你注册彩票网站seo的优点有哪些
  • 做网站用什么cms网站模板哪里好
  • 网络营销案例分析范文游戏行业seo整站优化
  • 网上商城都有哪些平台河南seo优化
  • 旅游网站做模板素材凡科建站后属于自己的网站吗
  • 在哪做网站专业网络舆情分析师
  • 网站咨询窗口怎么做广东seo网站设计
  • 巴中哪里可以做公司网站硬件工程师培训机构哪家好
  • 网站建设与维护 参考文献项目营销策划方案
  • 网站建设销售员自动app优化最新版