Java 线程

Java 线程

package test_02;
/*
线程常用的方法:
     Thread(String name)       初始化线程的名字
     setName(String name)      设置线程对象名
     getName()                 返回线程的名字
     sleep()                   线程睡眠指定的毫秒数。 静态的方法,那个线程执行了sleep方法代码那么就是那个线程睡眠。     
     currentThread()           返回当前的线程对象,该方法是一个静态的方法,注意:那个线程执行了currentThread()代码就返回那个线程的对象。
     getPriority()             返回当前线程对象的优先级   默认线程的优先级是5
     setPriority(int newPriority) 设置线程的优先级    虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现(最大的优先级是10 ,最小的1 , 默认是5)。
     
*/
public class thread_03 extends Thread{
    
    public thread_03 (String name)
    {
        super(name);
    }
    
    @Override
    public void run() {
        for(int i=0;i<100;i++)
        {
            System.out.println(this.getName()+":"+i);
            try {
                sleep(100);   //为什么在这里不能抛出异常,只能捕获?? Thread类的run方法没有抛出异常类型,所以子类不能抛出异常类型。
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        thread_03 th1=new thread_03("线程1");
        System.out.println(th1.getName());
        th1.sleep(5000);   //这个是主线程在睡眠!!!这个代码是主线程在调用!!!对象并不起作用!!!
        th1.setName("new name ...");
        th1.start();
        Thread mainthread=Thread.currentThread();   //当年线程对象
        System.out.println("主线程的名字:"+mainthread.getName());
    }
}

运行结果:

线程1
主线程的名字:main
new name ...:0
new name ...:1
new name ...:2
new name ...:3
new name ...:4
new name ...:5
new name ...:6
new name ...:7
new name ...:8
new name ...:9
new name ...:10

 

 

public class thread_03 extends Thread{
    
    public thread_03 (String name)
    {
        super(name);
    }
    
    @Override
    public void run() {
        System.out.println("this:"+ this);
    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        thread_03 th1=new thread_03("线程1");
        System.out.println("th1:"+th1);
        th1.start();
    }
}

运行结果:

th1:Thread[线程1,5,main]
this:Thread[线程1,5,main]

 

 

package test_02;
/*
线程常用的方法:
     Thread(String name)       初始化线程的名字
     setName(String name)      设置线程对象名
     getName()                 返回线程的名字
     sleep()                   线程睡眠指定的毫秒数。 静态的方法,那个线程执行了sleep方法代码那么就是那个线程睡眠。     
     currentThread()           返回当前的线程对象,该方法是一个静态的方法,注意:那个线程执行了currentThread()代码就返回那个线程的对象。
     getPriority()             返回当前线程对象的优先级   默认线程的优先级是5
     setPriority(int newPriority) 设置线程的优先级    虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现(最大的优先级是10 ,最小的1 , 默认是5)。
     
*/
public class thread_03 extends Thread{
    
    public thread_03 (String name)
    {
        super(name);
    }
    
    @Override
    public void run() {
        System.out.println("this:"+ this);
    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        thread_03 th1=new thread_03("线程1");
        th1.setPriority(10);
        System.out.println("th1:"+th1);
        System.out.println("自定义线程的优先级:"+th1.getPriority());

    }
}

 

运行结果:

th1:Thread[线程1,10,main]
自定义线程的优先级:10

 

 

 

/*
需求: 模拟3个窗口同时在售50张票 。

问题1 :为什么50张票被卖出了150次?
出现的原因:因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。
解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。

*/

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){    
                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 thread_04 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建三个线程对象,模拟三个窗口
                SaleTicket thread1 = new SaleTicket("窗口1");
                SaleTicket thread2 = new SaleTicket("窗口2");
                SaleTicket thread3 = new SaleTicket("窗口3");
                //开启线程售票
                thread1.start();
                thread2.start();
                thread3.start();
    }
}

 

运行结果:

窗口1售出了第50号票
窗口3售出了第50号票
窗口2售出了第50号票
窗口1售出了第48号票
窗口2售出了第47号票
窗口3售出了第48号票
窗口2售出了第45号票
窗口3售出了第44号票
窗口1售出了第45号票
窗口2售出了第42号票
窗口3售出了第41号票

 

 

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

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

*/
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(o){         // 同步代码块     
            //synchronized("锁子")    // 这也是基本的锁子,因为字符串已经在存在在字符串常量池,不会再创建。
                if(num>0){
                    System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
                    try {
                        Thread.sleep(100);                  
                        //  在同步代码块中调用了sleep方法并不是释放锁对象的。
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num--;
                }else{
                    System.out.println("售罄了..");
                    break;
                }
            }
        }
    }    
} 

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

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

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

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

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

运行结果:

窗口1售出了第50号票
窗口2售出了第49号票
窗口2售出了第48号票
窗口2售出了第47号票
窗口3售出了第46号票
窗口3售出了第45号票
窗口3售出了第44号票
窗口2售出了第43号票
窗口2售出了第42号票
窗口1售出了第41号票
窗口1售出了第40号票
窗口1售出了第39号票
窗口1售出了第38号票
窗口2售出了第37号票
窗口2售出了第36号票
窗口3售出了第35号票
窗口3售出了第34号票
窗口3售出了第33号票
窗口3售出了第32号票
窗口3售出了第31号票
窗口3售出了第30号票
窗口3售出了第29号票
窗口3售出了第28号票
窗口2售出了第27号票
窗口2售出了第26号票
窗口2售出了第25号票
窗口2售出了第24号票
窗口1售出了第23号票
窗口1售出了第22号票
窗口1售出了第21号票
窗口1售出了第20号票
窗口1售出了第19号票
窗口2售出了第18号票
窗口3售出了第17号票
窗口2售出了第16号票
窗口2售出了第15号票
窗口2售出了第14号票
窗口2售出了第13号票
窗口2售出了第12号票
窗口1售出了第11号票
窗口2售出了第10号票
窗口2售出了第9号票
窗口2售出了第8号票
窗口3售出了第7号票
窗口3售出了第6号票
窗口2售出了第5号票
窗口2售出了第4号票
窗口1售出了第3号票
窗口1售出了第2号票
窗口1售出了第1号票
售罄了..
售罄了..
售罄了..

 

同步代码块的原理:

 

 

 

转载于:https://my.oschina.net/hellation/blog/3061644

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值