zhangsan运行 : 0
sunny运行 : 0
sunny运行 : 1
sunny运行 : 2
zhangsan运行 : 1
zhangsan运行 : 2
zhangsan运行 : 3
sunny运行 : 3
zhangsan运行 : 4
sunny运行 : 4
注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的;多线程程序是乱序执行。多个线程分别完成自己的任务。
 

2.2 实现Runnable

多个线程共同完成一个任务;不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的。
 

2.3 实现Callable

使用Callable+Future获取执行结果,并且可以抛出异常。
public class CallableDemo implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        System.out.println("Callable子线程开始计算啦!" + Thread.currentThread().getName());
        Thread.sleep(2000);
    
        for(int i=0 ;i<5000;i++){
            sum=sum+i;
        }
        System.out.println("Callable子线程计算结束!" + Thread.currentThread().getName());
        return sum;
    }
}

Callable执行测试类如下:

public class CallableTest {  
    public static void main(String[] args) {  
        //创建线程池  
        ExecutorService es = Executors.newSingleThreadExecutor();
        //创建Callable对象任务  
        CallableDemo calTask = new CallableDemo();
        //提交任务并获取执行结果  
        Future<Integer> future = es.submit(calTask);
        //关闭线程池  
        es.shutdown();
        try {
            Thread.sleep(2000);
            System.out.println("主线程在执行其他任务");
    
            if (future.get() != null) {
                //输出获取到的结果  
                System.out.println("future.get()-->" + future.get());
            } else {

                //输出获取到的结果  
                System.out.println("future.get()未获取到结果");
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("主线程在执行完成");  
    }  
}

2.4 总结

实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类