完美解决Java中的线程安全问题

给出一个问题,如下:

解决方案如下:

public class Demo_5 {

 public static void main(String[] args) {
  //创建一个窗口
  TicketWindow tw1=new TicketWindow();

  //使用三个线程同时启动
  Thread t1=new Thread(tw1);
  Thread t2=new Thread(tw1);
  Thread t3=new Thread(tw1);

  t1.start();
  t2.start();
  t3.start();
 }

}

//售票窗口类
class TicketWindow implements Runnable{
 private int nums=2000;       //一共2000张票

 @Override
 public void run() {
  while(true){  

    if(nums>0){      //先判断是否还有票
     //Thread.currentThread().getName()得到当前线程的名字
     System.out.println(Thread.currentThread().getName()+"在售出第"+nums+"张票"); //显示售票信息

     //出票的速度是一秒出一张
     try {
      Thread.sleep(1000);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }

     nums--;
    }else{
     break;       //售票结束
    }

  }
 }
}

执行这段代码发现问题,就是同一张票号可能被多个售票窗口出售,惹祸的代码就是if else语句块。

解决方法就是在需要同步的代码段用synchronized(Object){你要同步的代码}即可。

修改后代码如下:

public class Demo_5 {

 public static void main(String[] args) {
  //创建一个窗口
  TicketWindow tw1=new TicketWindow();

  //使用三个线程同时启动
  Thread t1=new Thread(tw1);
  Thread t2=new Thread(tw1);
  Thread t3=new Thread(tw1);

  t1.start();
  t2.start();
  t3.start();
 }

}

//售票窗口类
class TicketWindow implements Runnable{
 private int nums=2000;       //一共2000张票

 @Override
 public void run() {
  while(true){
   //认为if else这段代码要保证其原子性(同步代码块)
   synchronized (this) {

    if(nums>0){        //先判断是否还有票
     //Thread.currentThread().getName()得到当前线程的名字
     System.out.println(Thread.currentThread().getName()+"在售出第"+nums+"张票"); //显示售票信息

     //出票的速度是一秒出一张
     try {
      Thread.sleep(1000);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }

     nums--;
    }else{
     break;       //售票结束
    }

   }
  }
 }
}

执行这段代码发现出票正常了。

线程1正执行需要做同步处理的代码,线程2,3,4……blocked,被放入了线程等待池,就好像某人上厕所前先把门关上(上锁),完事之后再出来(解锁),然后别人就可以继续使用了。

以上这篇完美解决Java中的线程安全问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 基于java线程安全问题及原理性分析

    1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题:如果在整个访问过程中,无一对象被其他线程修改,就是线程安全的. 2.线程安全问题产生的根本原因 首先是多线程环境,即同时存在有多个操作者,单线程环境不存在线程安全问题.在单线程环境下,任何操作包括修改操作都是操作者自己发出的,操作者发出操作时不仅有明确的目的,而且意识到操作的影响. 多个操作者(线程)必须操作同一个对象,只有多个操作者同时操作一个对象,行为

  • Java ThreadLocal 线程安全问题解决方案

    一.线程安全问题产生的原因 线程安全问题都是由全局变量及静态变量引起的 二.线程安全问题 SimpleDateFormate sdf = new SimpleDateFormat();使用sdf.parse(dateStr);sdf.format(date);在sdf内有一个对Caleadar对象的引用,在源码sdf.parse(dateStr);源码中calendar.clear();和calendar.getTime(); // 获取calendar的时间 如果 线程A 调用了 sdf.pa

  • Java线程安全问题小结_动力节点Java学院整理

    浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的.其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改.总结java的内存模型,要解决两个主要的问题:可见性和有序性.我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的.JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节,对于java开发人员,要清楚在jvm内存模型的基础上,如果解决多线程的可见性和有序性. 那么,何谓

  • 分享40个Java多线程问题小结

    Java多线程是什么 Java提供的并发(同时.独立)处理多个任务的机制.多个线程共存于同一JVM进程里面,所以共用相同的内存空间,较之多进程,多线程之间的通信更轻量级.依我的理解,Java多线程完全就是为了提高CPU的利用率.Java的线程有4种状态,新建(New).运行(Runnable).阻塞(Blocked).结束(Dead),关键就在于阻塞(Blocked),阻塞意味着等待,阻塞的的线程不参与线程分派器(Thread Scheduler)的时间片分配,自然也就不会使用到CPU.多线程环

  • 完美解决Java中的线程安全问题

    给出一个问题,如下: 解决方案如下: public class Demo_5 { public static void main(String[] args) { //创建一个窗口 TicketWindow tw1=new TicketWindow(); //使用三个线程同时启动 Thread t1=new Thread(tw1); Thread t2=new Thread(tw1); Thread t3=new Thread(tw1); t1.start(); t2.start(); t3.s

  • 解决Java中SimpleDateFormat线程不安全的五种方案

    目录 1.什么是线程不安全? 线程不安全的代码 2.解决方案 ① 将SimpleDateFormat变为局部变量 ② 使用synchronized加锁 ③ 使用Lock加锁 ④ 使用ThreadLocal ⑤ 使用DateTimeFormatter 3.线程不安全原因分析 4.各方案优缺点总结 1.什么是线程不安全? 线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫做线程不安全. 线程不安全的代码 SimpleDateFormat 就是一个典型的线程不安全事例

  • Java中关于线程安全的三种解决方式

    三个窗口卖票的例子解决线程安全问题 问题:买票过程中,出现了重票.错票-->出现了线程的安全问题 问题出现的原因:当某个线程操作车票的过程中,尚未操作完成时,其他线程参与进来,也操作车票 如何解决:当一个线程a在操作ticket的时候,其他线程不能参与进来,知道线程a操作完ticket时,其他线程才可以开始操作ticket,这种情况即使线程a出现了阻塞,也不能被改变 在Java中,我们通过同步机制,来解决线程的安全问题.(线程安全问题的前提:有共享数据) 方式一:同步代码块 synchroniz

  • Struts中action线程安全问题解析

    [问题描述] 最近公司安排我面试Java的FreshMan,面试者一般是工作1年多点的新人(这里我就装老一下,其实我也才工作3年不到),在被问及Struts1和Struts2的Action的线程安全问题的时候,大多是支支吾吾,答不出所以然.所以在这里我整理一下我个人的理解. [问题答案] 这是由于Servlet的工作原理产生的.我们先来简单回顾一下Servlet的生命周期"初始化->init->service->destroy->卸载". 这里大家都知道,我们在

  • Java多线程之线程安全问题详情

    目录 1.线程安全概述 1.1什么是线程安全问题 1.2一个存在线程安全问题的程序 2.线程加锁与线程不安全的原因 2.1案例分析 2.2线程加锁 2.2.1什么是加锁 2.2.2如何加锁 2.2.3再析案例 2.3线程不安全的原因 3.线程安全的标准类 4.Object类提供的线程等待方法 前言: 本篇文章介绍的内容为Java多线程中的线程安全问题,此处的安全问题并不是指的像黑客入侵造成的安全问题,线程安全问题是指因多线程抢占式执行而导致程序出现bug的问题. 1.线程安全概述 1.1什么是线

  • 完美解决java读取大文件内存溢出的问题

    1. 传统方式:在内存中读取文件内容 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path)); 实际上是使用BufferedReader或者其子类LineNumberReader来读取的. 传统方式的问题: 是文件的所有行都被存放在内存中,当文件足够大时很快就会

  • 完美解决java.lang.OutOfMemoryError处理错误的问题

    原因: 常见的有以下几种: 1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 3.代码中存在死循环或循环产生过多重复的对象实体: 4.使用的第三方软件中的BUG: 5.启动参数内存值设定的过小: 常见错误提示: 1.tomcat:java.lang.OutOfMemoryError: PermGen space 2.tomcat:java.lang.OutOfMemoryError: Java heap space 3

  • Java中启动线程start和run的两种方法

    一.区别 Java中启动线程有两种方法,继承Thread类和实现Runnable接口,由于Java无法实现多重继承,所以一般通过实现Runnable接口来创建线程.但是无论哪种方法都可以通过start()和run()方法来启动线程,下面就来介绍一下他们的区别. start方法: 通过该方法启动线程的同时也创建了一个线程,真正实现了多线程.无需等待run()方法中的代码执行完毕,就可以接着执行下面的代码.此时start()的这个线程处于就绪状态,当得到CPU的时间片后就会执行其中的run()方法.

  • 完美解决Java获取文件路径出现乱码的问题

    在Java中有时获取文件路径,获取的路径中存在中文或者是空格的时候,路径出现乱码.这个问题困扰了我好久,用过各种的转码都无济于事.在后来终于解决了,在这里和大家分享一下,其实也就是加一行代码的问题. 我在项目的是使用 String path = this.getClass().getClassLoader().getResource("/").getPath().substring(1); 这样来获得当前类的文件路径的.但是这样得到的是乱码.后来经过跟踪 在this.getClass(

  • 浅谈Java中ArrayList线程不安全怎么办

    ArrayList线程不安全怎么办? 有三种解决方法: 使用对应的 Vector 类,这个类中的所有方法都加上了 synchronized 关键字 就和 HashMap 和 HashTable 的关系一样 使用 Collections 提供的 synchronizedList 方法,将一个原本线程不安全的集合类转换为线程安全的,使用方法如下: List<Integer> list = Collections.synchronizedList(new ArrayList<>());

随机推荐