简单入门java多线程<一>:源码分析Thread和Runnable

来源:互联网 发布:photoshop软件购买 编辑:程序博客网 时间:2024/05/29 15:30

简单入门,如果要深入的话,期待之后的《多线程进阶》《安全多线程》吧。这篇文章将会从源码的角度比较清晰的展现java多线程的应用,避免一团雾水吧。

begin!
一、java实现多线程两种方式
(1)继承thread
public class BaseThread extends Thread{public BaseThread(String name) {super(name);}public void run() {        for (int i = 0; i < 5; i++) {            System.out.println(Thread.currentThread().getName() + "  运行中---  " + i);        }    }public static void main(String[] args) {new BaseThread("线程007").start();}}
(2)实现Runnable
public class BaseRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 5; i++) {            System.out.println(Thread.currentThread().getName() + "  运行中---  " + i);        }}public static void main(String[] args) {new Thread(new BaseRunnable(), "线程007").start();}}
两者的运行结果相同。
好,接下来讨论两个经典的问题。
(a)调用run方法和调用start方法区别
run():本质就是调用成员方法,依然运行在主线程中,不会立即返回(等run方法执行完毕,才会继续执行主线程的其他方法)
start():启动线程,并调用run()方法。(start)方法立即返回,(run)方法则与其他线程并行运行。
看下源码(片段):重点在注释
public class Thread implements Runnable {    public synchronized void start() {//运行时占用当前Thread对象的同步锁                if (threadStatus != 0 || this != me)            throw new IllegalThreadStateException();//重复调用抛异常        group.add(this);//将当前线程对象添加到线程组        start0();//此时该线程由VM(虚拟机)调用        if (stopBeforeStart) {    stop0(throwableFromStop);}    }    //本地方法,通过C实现线程    private native void start0();    //target就是Runnable的引用,所以如果继承Thread则需要重写run方法,因为此时target为null。    //而实现Runnable接口的话,此时会调用target所指向的引用中的run方法。    public void run() {if (target != null) {    target.run();}    }}
总之,调用run()方法并没有启动新线程,没有任何意义。
有空可以自己去看看源码,那才是了解java的最好方式。
 (b)Thread和Runnable区别,该选谁?
Thread:各花各的钱
public class MoneyThread extends Thread{private int money = 100;//初始钱数public MoneyThread(String name) {super(name);}public void run() {//每次线程,花两次钱for(int i = 0;i<2;i++){money = money-10;        System.out.println(Thread.currentThread().getName() + "  花了10元钱,剩余 " + money);}    }public static void main(String[] args) {new MoneyThread("张三").start();new MoneyThread("李四").start();}}/*结果:张三 花了10元钱,剩余 90李四  花了10元钱,剩余 90张三  花了10元钱,剩余 80李四  花了10元钱,剩余 80*/
Runnable:有钱大家一起花
public class MoneyRunnable implements Runnable{private int money = 100;//初始钱数--共享资源@Overridepublic void run() {//每次线程,花两次钱for(int i = 0;i<2;i++){synchronized (this) {//当资源共享时,必须使用同步,来保证数据一致性money = money-10;System.out.println(Thread.currentThread().getName() + "  花了10元钱,剩余 " + money);}}}public static void main(String[] args) {MoneyRunnable moneyRunnable = new MoneyRunnable();new Thread(moneyRunnable,"张三").start();new Thread(moneyRunnable,"李四").start();}}/*结果:张三  花了10元钱,剩余 90张三  花了10元钱,剩余 80李四  花了10元钱,剩余 70李四  花了10元钱,剩余 60*/
当然,Runnable可以一起花,也可以分开花,只要分别建立MoneyRunnable实例就行
总的来说:
1、实现Runnable可以实现资源共享
2、java是单继承,如果继承Thread,那就无法再继承其他类
3、其实看Thread的源码,它本身就是实现了Runnable接口

所以大部分时候,还是选择通过实现Runnable接口的方式来实现多线程。
当然Thread之所以存在,必然有其意义。只是暂时我还没想到。(阿里面试有问的哟)

额,突然发现一篇写不完了,等续集吧,java多线程,入门也不易啊


0 0
原创粉丝点击