您的位置:首页 > 其它

线程及线程安全解决方法

2017-12-09 09:37 127 查看
/*

/*

线程:

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

自定义线程的创建方式:

    

    方式一:继承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();

        

    }

    
}

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐