java中的线程

     关于java中的线程主要介绍一下以下几个方面:1、线程的创建和启动    2、线程的生命周期      3、线程同步(重点)   

---------------------------------------------------------------------------------

 

    1、线程的创建和启动:

         i)线程的创建:线程的创建有两种方式:继承java.lang.Thread类;实现java.lang.Runable接口。

            对于继承java.lang.Thread类的线程,在创建了这个线程以后,我们要重写该类的run()方法,而run方法的方法体是当前该线程要做的事情。

            对于实现java.lang.Runable接口的线程,在创建了该线程之后,也要实现run()方法。(注意:其中java.lang.Thread这个类也是实现了java.lang.Runable接口的)。eg:

public class MyThread1 extends Thread{
 
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}
 
public class MyThread2 implements Runnable{
 
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

         以上两个线程分别使用两种方式被创建。run方法都是循环100次输出当前线程的名字。在第二种方式中,由于java.lang.Thread这个类也是实现了java.lang.Runable接口,所以可以使用Thread类的方法currentThread()方法来获得当前线程。

         ii)线程的启动:线程的启动要使用start()方法。我们首先创建一个main方法,在main方法中启动线程,eg

public class Test{
    public static void main(String[] args){
        MyThread1 m1 = new MyThread1();
        m1.start();
         
        Thread t2 = new Thread(new MyThread2());
        t2.start();
    }
}

        对于线程二的启动,因为实现的是Runable接口,所以不能直接调用start方法,在Thread类的构造方法中,有一个参数是Runable接口的方法,由于MyThread2实现了该接口,所以使用 Thread类的该构造方法,启动start方法。

        建和启动线程,倒不是因为哪一种方式更好,而是考虑到java的单继承,当一个类已经继承了另外一个类时,就不能再去继承Thread类,只能去实现Runable接口。

 

   2、线程的生命周期:



        线程只能创建和死亡一次,但是线程的其他三种方式却是可以循环多次的。一个线程被创建后,就会进入就绪队列等待调度,当获得处理器资源后就会进入运行状态,当该线程的run方法全部运行完后,该线程就会死亡,或者就会进入阻塞状态,阻塞结束后重新进入就绪状态。或在运行过程中市区处理器资源,直接进入就绪状态等待,依次循环,直到线程死亡。

 

    3、线程同步:

        在多线程中,当多个线程同时对同一个对象同一个实例变量操作时,就可能引起线程不同步问题。

        在此以两个人同时用一个账户取钱为例,说明并解决线程不同步的问题。

public class Account {
 
    private int money = 2000;   
    public void getMoney(String name,int money) {
        //...此处省略1000行
            if(money < this.money) {
                this.money -= money;
                System.out.println(name + "取款成功");
            } else {
                System.out.println(name + "余额不足");
            }       
    }
}

 

public class Rose extends Thread{
 
    private Account account;
     
    public Rose(Account account) {
        this.account = account;
    }
     
    @Override
    public void run() {
        try {
            Thread.sleep(300);
            account.getMoney("rose", 1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

public class Tom extends Thread{
 
    private Account account;
     
    public Tom(Account account) {
        this.account = account;
    }
     
    @Override
    public void run() {
     
        try {
            Thread.sleep(300);
            account.getMoney("tom", 1500);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
     
}

 

public class Test{
    public static void main(String[] args){
        Account account = new Account();
         
        Tom tom = new Tom(account);
        Rose rose = new Rose(account);
         
        tom.start();
        rose.start();
    }
}

         运行结果截图:




  


         之所以出现不同的结果,是因为对于两个不同的线程Rose和Tom调用account的takeMoney()方法时出现的线程的切换,当第一个线程完成if条件判断时,处理器资源突然给了另一个线程。这就造成了线程不同步,即现成不安全。

 

          解决方案1:在方法声明上添加关键字synchronized,即对于Account类中的方法takeMoney()这样声明:public synchronized void takeMoney(),这样一旦一个线程run方法运行到这个方法时,就会上锁,阻止其他线程进入。从而实现线程同步。

          解决方案2:使用synchronized同步代码块。我们只对可能引起线程不同步的那一部分代码上锁,而不是对整个方法上锁,从而提高程序的运行效率。即:将if选择包括在同步代码块中。

public class Account {
 
    private int money = 2000;   
    public void getMoney(String name,int money) {
        //...此处省略1000行
                    synchronized(this){
            if(money < this.money) {
                this.money -= money;
                System.out.println(name + "取款成功");
            } else {
                System.out.println(name + "余额不足");
            }
                    } <span></span> }
}

          解决方案3:同步锁,引入java.util.concurrent.locks.ReentrantLock。在if选择运行前加锁,运行完这些代码后,在解锁。代码如下:

public class Account {
 
    private int money = 2000;
    private ReentrantLock reentrantLock = new ReentrantLock();
     
    public void getMoney(String name,int money) {
        //...此处省略1000行
        try{
            reentrantLock.lock();
            if(money < this.money) {
                this.money -= money;
                System.out.println(name + "取款成功");
            } else {
                System.out.println(name + "余额不足");
            }
        } finally {
            reentrantLock.unlock();
        }
         
    }
}

 

    到此为止,javaSE就算告一段落了。期待后续补充、、、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值