线程及线程安全解决方法

来源:互联网 发布:绝食瘦下来知乎 编辑:程序博客网 时间:2024/06/07 09:30

/*


/*
线程:

多线程的好处: 多线程解决了在一个进程中同时可以执行多个任务代码的问题。


自定义线程的创建方式:

    
    方式一:继承Thread.
        1. 自定义一个类继承Thread类。
        2. 重写Thread的run方法,把自定义线程的任务代码定义在run方法上。
        3. 创建Thread子类的对象,并且调用start方法启动一个线程。

    
    方式二: 实现Runnable接口。
        1. 自定义一个类实现Runnable接口。
        2. 实现Runnable接口中的run方法,把自定义线程的任务代码定义在run方法上。
        3. 创建Runable实现类 的对象。
        4. 创建Thread对象,并且把Runnable实现类的对象作为参数传递。
        5. 调用Thread对象的start方法开启线程。
        
线程安全 问题的解决方案:

线程安全问题出现 的根本原因:
    1. 必须要存在两个或者两个以上的线程共享着一个资源。
    2. 操作共享资源的代码必须有两句或者两句以上。
    


    1. 同步代码块
        
        synchronized(锁){
            需要被同步的代码
        }
        
        
        
    2. 同步函数。
        
        修饰符 synchronized 返回值类型   函数名(形参列表..){
        
        }
        
        
    注意:
        1. 同步代码块的锁可以是任意的对象。 同步函数的锁是固定 的,非静态函数的锁对象是this对象。 静态函数的锁对象是class对象。
        2. 锁对象必须是多线程共享的对象,否则锁不住。
        3. 在同步代码块或者是同步函数中调用sleep方法是不会释放锁对象的,如果是调用了wait方法是会释放锁对象的。

 */

public class Demo1 extends Thread {
    
    
    public Demo1(String name){
        super(name);
    }
    
    @Override
    public void run() {
        for(int i = 0 ; i< 100 ; i++){
            System.out.println(Thread.currentThread().getName()+":"+ i);
        }
    }
    
    public static void main(String[] args) {

        Demo1 d = new Demo1("狗娃");
        d.start(); //开启线程。 线程一旦开启就会指定run方法中 的代码。
        
        
        for(int i = 0 ; i< 100 ; i++){
            System.out.println(Thread.currentThread().getName()+":"+ i);
        }
    }
    

}


/*
 需求: 模拟3个窗口同时在售50张 票 。
 
问题1 :为什么50张票被卖出了150次?

出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。

解决方案:把num票数共享出来给三个线程对象a使用。使用static修饰。

问题2: 出现了线程安全问题 ?

线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。
    
    java线程同步机制的方式:
    
        方式一:同步代码块
            
            同步代码块的格式:
                
                synchronized(锁对象){
                    需要被同步的代码...
                }

同步代码块要注意事项:
        1. 任意的一个对象都可以做为锁对象。
        2. 在同步代码块中调用了sleep方法并不是释放锁对象的。
        3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。
        4. 多线程操作的锁 对象必须 是唯一共享 的。否则无效。
        

需求: 一个银行账户5000块,两夫妻一个拿着 存折,一个拿着卡,开始取钱比赛,每次只能取一千块,要求不准出现线程安全问题。
        
        
        
        方式二:同步函数

出现线程安全问题的根本原因:
    1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。
    2. 有多个语句操作了共享资源。
    

 
 */

class SaleTicket extends Thread{
        
    
     static int num = 50;//票数  非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。
    
     static    Object o = new Object();
    
     public SaleTicket(String name) {
        super(name);
    }
    
    @Override
    public void run() {
        while(true){
            //同步代码块
            synchronized ("锁") {                
                if(num>0){
                    System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num--;
                }else{
                    System.out.println("售罄了..");
                    break;
                }
            }
            
        }
    }    
    
    
}


public class Demo4 {
    
    public static void main(String[] args) {
        //创建三个线程对象,模拟三个窗口
        SaleTicket thread1 = new SaleTicket("窗口1");
        SaleTicket thread2 = new SaleTicket("窗口2");
        SaleTicket thread3 = new SaleTicket("窗口3");
        //开启线程售票
        thread1.start();
        thread2.start();
        thread3.start();
        
    }
    

}

*/


原创粉丝点击