在Java中创建线程有两中方法,一种是实现Runnable接口,一种是继承Thread类
实现Runnable接口
将任务代码迁移到实现Runnable接口的类的run方法中
1 2 3 4 5 class MyRunnable implements Runnable { public void run () { task code } }
创建一个类对象: Runnable r = new MyRunnable()
由Runnable创建一个Thread对象 Thread t = new Thread(r)
启动线程 t.start() 完整例子如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class MyRunnable implements Runnable { @Override public void run () { System.out.println("Child: " + Thread.currentThread().getId()); } public static void main (String[] arg) { for (int i = 0 ; i < 5 ; i++) { Runnable r = new MyRunnable(); Thread t = new Thread(r); t.start(); } System.out.println("Parent: " + Thread.currentThread().getId()); } }
输出结果如下: Child: 8 Child: 9 Child: 10 Child: 11 Parent: 1 Child: 12 这里不能直接调用run方法,因为这样不会创建新的线程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class MyRunnable implements Runnable { @Override public void run () { System.out.println("Child: " + Thread.currentThread().getId()); } public static void main (String[] arg) { for (int i = 0 ; i < 5 ; i++) { Runnable r = new MyRunnable(); r.run(); } System.out.println("Parent: " + Thread.currentThread().getId()); } }
输出结果如下: Child: 1 Child: 1 Child: 1 Child: 1 Child: 1 Parent: 1 可以看到id都是一样的,也就是这里没有创建新的线程.
继承Thread类 1 2 3 4 5 class MyThread extends Thread { public void run() { task code } }
完整例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class MyThread extends Thread { @Override public void run () { System.out.println("Child: " + Thread.currentThread().getId()); } public static void main (String[] arg) { for (int i = 0 ; i < 5 ; i++) { Thread t = new MyThread(); t.start(); } System.out.println("Parent: " + Thread.currentThread().getId()); } }
输出结果如下: Child: 8 Child: 9 Child: 10 Child: 11 Parent: 1 Child: 12 这里不能直接调用t.run(),因为这样不会创建新的线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class MyThread extends Thread { @Override public void run () { System.out.println("Child: " + Thread.currentThread().getId()); } public static void main (String[] arg) { for (int i = 0 ; i < 5 ; i++) { Thread t = new MyThread(); t.run(); } System.out.println("Parent: " + Thread.currentThread().getId()); } }
结果如下: Child: 1 Child: 1 Child: 1 Child: 1 Child: 1 Parent: 1 可以看到id都是一样的。 查看Thread类的源码就会发现问题的所在.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM . Any new functionality added * to this method in the future may have to also be added to the VM . * * A zero status value corresponds to state "NEW" . */ if (threadStatus != 0 ) throw new IllegalThreadStateException (); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ 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();
在start方法中调用native方法start0(),虽然看不到它的具体实现,但可以推测这里创建了新的线程,然后调用run方法。而run方法中,则没有创建线程相关的代码
1 2 3 4 5 public void run () { if (target != null ) { target .run(); } }
关于两种方法的区别,可以看http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread , 推荐使用实现Runnable接口的方法。