package com.ivy.thread; public class FirstThread extends Thread{ private int i; public void run() { for( ; i < 100 ; i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args) { // TODO Auto-generated method stub for (int i = 0; i < 100 ; i++) { System.out.println(Thread.currentThread().getName()); if (i==20) { new FirstThread().start(); new FirstThread().start(); } } } }
2. 实现Runnable接口创建线程类
package com.ivy.thread; public class SecondThread implements Runnable{ private int i; public static void main(String[] args) { // TODO Auto-generated method stub for (int i = 0; i < 100 ; i++) { System.out.println(Thread.currentThread().getName()); if (i==20) { SecondThread st = new SecondThread(); new Thread(st, "newThread-1").start(); new Thread(st, "newThread-2").start(); } } } @Override public void run() { for( ; i < 100 ; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } }
在FirstThread和SecondThread中创建线程对象的方式有所区别:前者直接创建Thread字类即可代表线程对象;后者创建的Runnable对象只能作为线程对象的target。在FirstThread中Thread-0和Thread-1两个线程输出的i变量不连续--注意:i变量是FirstThread的实例属性,而不是局部变量,但因为程序每次创建线程对象时都需要创建一个FirstThread对象,所以Thread-0和Thread-1 不能共享该实例变量。但在SecondThread的输出结果中,两个子线程的i变量是连续的,也就是采用Runnable接口的方式创建的多个线程可以共享线程类的实例属性。
3. 使用Callable和Future创建线程
(1)创建Callable接口的实现类,并实现call方法,call方法有返回值
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get方法来获得子线程执行结束后的返回值。
package com.ivy.thread; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class ThirdThread implements Callable<Integer>{ public static void main(String[] args) { // TODO Auto-generated method stub ThirdThread rt = new ThirdThread(); FutureTask<Integer> task = new FutureTask<Integer>(rt); for (int i =0; i< 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 20) { new Thread(task, "hasReturnThread").start(); } } try { System.out.println("sub Thread return : " + task.get()); } catch (Exception ex) { ex.printStackTrace(); } } @Override public Integer call() throws Exception { int i = 0; for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } return i; } }
4. 创建线程的三种方式对比
通过继承Thread类或实现Runnable/Callable接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已。一般采用实现Runnable/Callable接口来创建多线程。
5. 线程状态
A 新建
B 就绪
C 运行
D 阻塞
E 死亡
当主线程结束时,其他线程不受任何影响,并不会随之结束,一旦子线程启动起来之后,它就拥有和主线程相同的地位,它不受主线程的影响。
原文:http://www.cnblogs.com/IvySue/p/6418261.html