• Java再学习——线程之创建


    Java创建线程有两种方法,一种是继承Thread,另一种实现Runnable或Callable接口。

    一,继承Thread

    public class APP {
    
        public static void main(String[] args) {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    int i = 0;
                    while (i < 100) {
                        System.out.println(i++);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            thread.start();
        }
    }

    上述例子通过重写Thread的run方法,来定时输出i的值,但是要主要Thread的run方法仅仅是个普通的方法,必须要通过调用start方法才能创建线程去执行run方法,直接调用run就没有线程的创建了。

    二,实现Runnable或Callable接口来创建线程。

    这两个接口的实现只能是变成一个普通的类,要创建线程都必须要通过其他相关类开启的。

    这两个接口最大的区别:Callable有返回值且能抛出受检测异常,而Runnable没有返回值也无法抛出受检测异常;

    1,对于Runnable接口来说,

      要通过它来创建线程的的方法有两种,一种是通过Thread,另一种是通过Executor

    public class APP {
    
        public static void main(String[] args) {
    
            class MyRunnable implements Runnable {
                @Override
                public void run() {
                    System.out.println("start -> "
                            + Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("end -> " + Thread.currentThread().getName());
                }
    
            }
    
            Thread thread = new Thread(new MyRunnable());
            thread.start();
    
            Executor executor = Executors.newSingleThreadExecutor();
            executor.execute(new MyRunnable());
        }
    }

    2,对于Callable接口来说,

      要通过它来创建线程的的方法有两种,一种是通过Thread,另一种是通过ExecutorService,但是都要同时借助于Future接口来实现对Callable返回值的相关控制。这里的ExecutorService接口是继承了Executor接口的,它增加了一些功能,大家可以点开源码看看就知道,而实例化都是通过Executors类的静态方法来实现的。

    2.1 通过Thread去创建

      由于Thread只能接受Runnable所以要想通过Thread去创建Callable线程,还要再借助一个即继承了Callable接口也继承了Runnable接口的类,这个类就是FutureTask。

    2.2 通过ExecutorService去创建

      由于ExecutorService天然支持Callable接口,所以直接submit就可以了。

    public class APP {
    
        public static void main(String[] args) throws Exception {
    
            class MyCallable implements Callable<Integer> {
                @Override
                public Integer call() throws Exception {
                    Thread.sleep(3000);
                    System.out.println("end");
                    return 200;
                }
            }
    
            ExecutorService es = Executors.newCachedThreadPool();
            Future<Integer> future = es.submit(new MyCallable());
            System.out.println("when ExecutorService -> " + future.get());
    
            FutureTask<Integer> task = new FutureTask<Integer>(new MyCallable());
            Thread thread = new Thread(task);
            thread.start();
            System.out.println("when Thread ->" + task.get());
        }
    }

    备注:

    Future的get方法是线程阻塞的,直到Callable的call()方法返回值为止。

    再次提醒创建线程不要直接调用run方法。

    如果发现理解不了,最好点进去看看源码。

  • 相关阅读:
    ajax原理及封装
    javascript 递归调用
    CSS的五种定位方式
    vue中iframe结合window.postMessage实现父子页面间的通信
    vue将文件流的形式的图形验证码转换成图片
    路由跳转打开新窗口,传递的参数不显示在地址栏
    js判断是否是ie浏览器、360浏览器兼容模式、QQ浏览器兼容模式、搜狗浏览器兼容模式,弹出提示使用别的浏览器打开
    vue项目中使用iframe嵌入静态页面,动态获取静态页面的高度赋值给iframe的高度
    vue项目中使用iview组件中的table插件实现表头文字居中,内容文字居左
    vue前端开发实现微信支付和支付宝支付
  • 原文地址:https://www.cnblogs.com/wytings/p/4946682.html
Copyright © 2020-2023  润新知