• 0302 线程状态、线程安全


    线程状态

    1、新建状态

    2、受阻塞状态

    3、运行状态

    4、死亡状态

    5、休眠状态

    6、等待状态

    线程安全

    当多条线程共用一份资源的时候就睡产生线程安全,比如电影院我们有100张票,同时有三个渠道去卖这100张票,看一下案例思维图

     我们来模拟一下这个场景

    首先创建一个线程类 实现Runnable接口,并且重写run方法

    public class Ticket implements Runnable{
    	private int num=100;
    	//卖票
    	public void run() {
    		while(true){
    			if(num>0){
    				try {
    					Thread.sleep(500);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
    			}
    		}
    	}
    }
    

      

    创建一个测试类,创建三条线程去卖票

    	public static void main(String[] args) {
    		//创建线程任务
    		Ticket t=new Ticket();
    		//创建三条线程
    		Thread t1=new Thread(t);
    		Thread t2=new Thread(t);
    		Thread t3=new Thread(t);
    		//开启线程
    		t1.start();
    		t2.start();
    		t3.start();
    	}
    

      根据运行结果会发现,会有第0张和第-1张 还有可能会出现多条线程卖同一张票的情况

     这就出现了线程安全问题,解决这个线程安全的方法

    1、同步代码块

    2、同步方法

    3、lock接口

    用到的是Synchronized关键字

    1、同步代码块格式

    synchronized (锁对象) {

        可能会产生线程安全问题的代码

    }

    同步代码块的锁对象可以是任意对象,但要保证该对象是唯一的

    代码展示

    public class Ticket02 implements Runnable{
    
    	private int num=100;
    	//定义一个锁对象
    	private Object obj=new Object();
    	//卖票
    	public void run() {
    		while(true){
    			synchronized (obj) {
    				if(num>0){
    					try {
    						Thread.sleep(500);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
    				}
    			}
    		}
    	}
    }
    

      

    2、同步方法

    格式:

    public synchronized void method(){

         可能会产生线程安全问题的代码

    }

    代码展示

    public class Ticket03 implements Runnable{
    
    	private int num=100;
    	//卖票
    	public void run() {
    		while(true){
    			sale();
    		}
    	}
    	//同步方法
    	public synchronized void sale(){
    		if(num>0){
    			try {
    				Thread.sleep(500);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
    		}
    	}
    }
    

      

    3、lock接口

    在loc接口中有两个方法

    (1)lock()获取锁

    (2)unlock()释放锁

    因为lock是个接口 那我们需要创建他的子类对象ReentrantLock去使用

    代码展示

    public class Ticket04 implements Runnable{
    
    	private int num=100;
    	//定义锁对象
    	private Lock lock=new ReentrantLock();
    	//卖票
    	public void run() {
    		while(true){
    			//获取锁
    			lock.lock();
    			if(num>0){
    				try {
    					Thread.sleep(500);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
    			}
    			//释放锁
    			lock.unlock();
    		}
    	}
    }
    

      

    那我们回想一下StringBuffer和StringBuilder这两个类完全相同,唯一的区别是StringBuilder比StringBuffer速度要快,是因为StringBuffer底层方法都用了Synchronized关键字,也就是说StringBuffer类能够保证线程安全,但StringBuilder类是不保证线程安全的,所以StringBuilder类适合在单线程中使用。

  • 相关阅读:
    AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式
    java如何得到GET和POST请求URL和参数列表
    Tomcat处理HTTP请求源码分析(下)
    Tomcat处理HTTP请求源码分析(上)(转)
    tomcat免重启随意更改java代码 提高开发效率
    ServletRequest中getReader()和getInputStream()只能调用一次的解决办法
    Spring MVC之@RequestParam @RequestBody @RequestHeader 等详解
    Tomcat处理HTTP请求源码分析(上)
    Drupal views中实现两列布局
    (转) 转换Drupal7模块到Drupal8
  • 原文地址:https://www.cnblogs.com/-gongxue/p/14467612.html
Copyright © 2020-2023  润新知