zoukankan      html  css  js  c++  java
  • 【Java并发编程一】线程安全问题

    1.多线程的实现

     

    多线程有两种实现方式:

    1.1.继承Thread类 =>示例:A a=new A(); a.start();


     

    1.2.实现Runnable接口 =>示例:A a=new A(); new Thread(A,自定义线程名称).start();


     

    其实Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式

    获取当前线程名称:Thread.currentThread().getName()

    调用线程是thread.start(),真正执行线程是 thread.run()

     

    具体代码:

     1 /**
     2  * 继承Thread类
     3  * @date 2019/3/29 11:19
     4  */
     5 public class SimpleThread extends Thread{
     6 
     7     @Override
     8     public void run() {
     9         super.run();
    10         Thread thread = Thread.currentThread();
    11         System.out.println("Thread =>当前执行的线程为:"+thread.getName());
    12     }
    13 }
    14 
    15 /**
    16  * 实现Runnable接口
    17  * @date 2019/3/29 11:28
    18  */
    19 public class SimpleRunnable implements Runnable {
    20 
    21     @Override
    22     public void run() {
    23          Thread thread = Thread.currentThread();
    24          System.out.println("Runnable =>当前执行的线程为:"+thread.getName());
    25     }
    26 }
    27 
    28 public class TestMain {
    29 
    30 
    31     /**执行线程示例1*/
    32     private static void callSimpleThread(){
    33         int index=10;
    34         for (int i = 0; i < index; i++) {
    35              Thread thread=new SimpleThread();
    36              thread.start();
    37         }
    38     }
    39 
    40     /**执行线程示例1*/
    41     private static void callSimpleRunnable(){
    42         int index=10;
    43         for (int i = 0; i < index; i++) {
    44             SimpleRunnable simpleRunnable=new SimpleRunnable();
    45             new Thread(simpleRunnable,"Runnable-"+i).start();
    46         }
    47     }
    48 
    49     public static void main(String[] args) {
    50 
    51         callSimpleThread();
    52 
    53         callSimpleRunnable();
    54     }
    55 
    56 }

     

     

    2.多线程安全问题

     

    2.1线程不安全示例

    多线程最容易产生的一个问题就是线程安全问题,下面使用一个卖票的例子来体现。
    场景描述:现在有两个售票员,一共卖10张车票
     1 public class SellTicket extends Thread {
     2 
     3     private static int NUMBER = 10;
     4     public SellTicket(String name) {
     5         super(name);
     6     }
     7 
     8     @Override
     9     public void run() {
    10         String s = "线程:" + Thread.currentThread().getName();
    11 
    12         while (NUMBER > 0) {
    13             int i = NUMBER--;
    14             System.out.println(s + " => 卖了第" + i + "号票");
    15         }
    16 
    17         System.out.println(s + ",票已经卖完");
    18         super.run();
    19     }
    20 
    21 
    22     public static void main(String[] args) {
    23 
    24         SellTicket thread1 = new SellTicket("售票员A");
    25         thread1.start();
    26 
    27         SellTicket thread2 = new SellTicket("售票员B");
    28         thread2.start();
    29 
    30     }
    31 
    32 }

    执行结果如下:

    我们发现售票员A 和售票员B都卖了10号票,这就是线程不安全导致的结果

     

     

    2.2线程不安全解决方法

    方案一:使用同步代码解决
    格式:synchronized(锁对象){需要被同步的代码}
    锁对象可以为this锁,也可以自定义对象锁

    方案二:使用同步函数解决
    同步函数就是使用synchronized修饰一个函数

      

    下面采用同步代码块解决

     1 public class SafetySellTicket extends Thread {
     2 
     3     private static int NUMBER = 10;
     4 
     5     @Override
     6     public  void run() {
     7         String s = "线程:" + Thread.currentThread().getName();
     8 
     9         while (NUMBER > 0) {
    10             synchronized (this) {
    11                 if (NUMBER > 0) {
    12                     int i = NUMBER--;
    13                     System.out.println(s + " => 卖了第" + i + "号票");
    14                 } else {
    15                     System.out.println(s + ",票已经卖完");
    16                     break;
    17                 }
    18 
    19             }
    20         }
    21         super.run();
    22     }
    23 
    24 
    25     public static void main(String[] args) {
    26 
    27         SafetySellTicket thread1 = new SafetySellTicket();
    28         thread1.start();
    29 
    30         SafetySellTicket thread2 = new SafetySellTicket();
    31         thread2.start();
    32 
    33     }
    34 
    35 }

     

  • 相关阅读:
    Javascript 获得数组中相同或不同的数组元素   
    Java IO流 FileOutputStream、FileInputStream的用法   
    你的项目中使用过哪些JSTL标签?
    JavaWeb代码复用
    软件质量保证体系是什么
    二叉树的递归遍历框架:
    二叉树节点的定义框架:
    SQL 2012 Always On 为 MSCRMSqlClrLogin SQL 登录名创建非对称密钥时报语法错误
    linux命令指usermod(管理用户以及权限的命令)
    Dynamics CRM 2013 SP1 升级到Dynamics CRM 2015
  • 原文地址:https://www.cnblogs.com/IT-study/p/10690605.html
Copyright © 2011-2022 走看看