1.继承Thread类,重写run方法,调用start方法。
这个方法是多线程中最简单的,但也是最普通的。
package cn.com.Thread; /* 创建多线程 继承Thread类,重写run方法,调用start方法 */ public class FirstThread extends Thread{ private int i; public void run(){ for (i = 0;i<100;i++){ System.out.println(getName()+" " + i); } } public static void main(String[] args) { for (int i = 0; i<100; i++){ System.out.println(Thread.currentThread().getName()+ " "+ i);//主线程 if(i == 20){ new FirstThread().start(); new FirstThread().start(); } } } }2.实现runnable接口,重写run方法,创建runnable实现类的实例st,以st作为Thread的target来创建thread的对象,这时的对象才是真的线程对象。
package cn.com.Thread; public class SecondThread implements Runnable{ private int i; public void run(){ for(i = 0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args) { for (int i = 0;i<30;i++){ System.out.println(Thread.currentThread().getName()+" "+ i ); if(i == 20){ SecondThread st = new SecondThread(); new Thread(st,"新线程1").start(); new Thread(st,"新线程2").start(); } } } }3.使用Callable和Future创建线程
创建了callable的实现类,并实现了call方法,可以通过实现类来创建callable对象,也可以用lambda表达式创建callable对象。
用FutureTask类来包装Callable对象,同时也包装了它的call方法和返回值。
用FutureTask的对象作为target,创建并启动。
用FutureTask的get方法获得返回值。
package cn.com.Thread; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class Thirdthread { public static void main(String[] args) { Thirdthread rt = new Thirdthread(); FutureTask<Integer> task = new FutureTask<>((Callable<Integer>)()->{ int i = 0; for (;i<30;i++) { System.out.println(Thread.currentThread().getName()+"主线程" +" "+i); } return i;//有返回值 }); for (int i = 0;i <30;i++){ System.out.println(Thread.currentThread().getName()+"次线程"+ " "+i); if (i == 20) { new Thread(task,"有返回值的线程").start(); } } try { System.out.println("子线程返回值"+ task.get()); }catch (Exception e){ e.printStackTrace(); } } }方法三有什么好处呢?答:可以抛出异常,有返回值。
总结:
法一:优点:简单,好用。
缺点:只能继承一个类,不能再继承其他父类了。
法二三:优点:只实现了接口,还可以继承其他父类。共享target,适合多线程共享同一个资源的情况。
缺点:编程稍稍复杂一点,如果访问当前线程,则使用Thread.currentThread()方法。