在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就能够实现多线程操做了,可是一个类只能继承一个父类,这是此方法的局限。java
可是实际在使用过程你会发现一些令你迷惑的问题,就来看下吧下面的代码:多线程
public class SeThread implements Runnable { private int i; @Override public void run() { for (; i < 20; i++) { System.out.println(Thread.currentThread().getName() + " i= "+ i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { if (i == 20) { SeThread st = new SeThread(); new Thread(st, "线程1").start(); new Thread(st, "线程2").start(); } } } }
能够看到,st是一个Runnable接口实现类的对象,可是却被两个线程做为参数,啊啊。这个打印结果是什么玩意??ide
看到这或许你已经猜到了,这个是两个Thread的外壳下竟然是同一颗跳到的Runnable心,那么仍是看下Thread的实现吧。this
public class Thread implements Runnable { public synchronized void start() { group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } private native void start0(); @Override public void run() { if (target != null) { target.run(); } } //…… }
其实,Thread就是Runnable实现类,在调用start过程当中,咱们能够知道它实现调用的是一个start0()这个本地方法,这个从咱们之前开发用的方法可知,确定是在CPU资源分配过程当中的某个时机调用了Thread的run()方法了,而run()方法实现的执行体就是传入的Runnable对象的runnable。.net
因此两个Thread的执行体,就是同一个runnale对象了,这个看上去是两个线程,可实际上只有一个执行体那就是st对象啦,打印结果确定是如上图看到的那样了。线程
其实这个打印有两个0,可知线程未同步,咱们能够在处理打印这个方法作个同步修饰synchronized,这样就能够正确的打印从0到99啦。code